TongTanapat
2 min readJan 20, 2019

--

มาเขียน Web scraping + Spread Sheet ผ่าน Python ด้วย Gspread กันครับ :)

https://downshiftology.com/recipes/cream-of-celery-soup/
https://apievangelist.com/2017/07/11/when-you-publish-a-google-sheet-to-the-web-it-als-becomes-an-api/

อันดับแรกเลยต้องบอกก่อนว่าไอเดียนี้เกิดจากการที่ผมต้องการเก็บข้อมูลจากเว็บข้อมูลประกาศตัวเลขสำคัญสำหรับการเทรดค่าเงินเว็บหนึ่งครับ ซึ่งทำให้สะดวกสบายกับชีวิตขึ้นมากกกก ไม่แน่ใจว่าบอกเว็บได้มั้ย เลยขอเอาเป็นว่าเอาลงโค้ดเฉพาะส่วนการเรียกใช้นะคร้าบ

  • Gspread จะรองรับ Python 2.7 ขึ้นไป ส่วน Version ที่ผมใช้อยู่คือ 3.6 ครับ

มาดู Code กันเลย ส่วนแรกที่ Import library ผมใช้ตัว request, BeautifulSoup และ Pandas ในการจัด Data frame ครับ

import requests
from bs4 import BeautifulSoup
import pandas
page = requests.get("Website that you need to collect data.")
content = page.content
soup = BeautifulSoup(content,"html.parser")

จากนั้นทำการ Create ตารางที่เราจะทำการเก็บข้อมูลขึ้นมา และผมเลือกที่จะเก็บข้อมูลในรูปแบบ Dict ครับ เราอยากได้หน้าตายังไง ข้อมูลอะไรบ้าง ก็จัดตรงนี้ได้เลยครับ แล้วเรียกผ่าน Pandas ออกมาดูกันครับ

สมมติว่าผมเก็บข้อมูลจากตารางการประกาศตัวเลขหน้าตาแบบนี้

table = soup.find_all("tr",{"class":"calendar_row"})
#print(table)
data = []
for item in table:
dict = {}

dict["Currency"] = item.find_all("td", {"class":"calendar__currency"})[0].text #Currency
dict["Event"] = item.find_all("td",{"class":"calendar__event"})[0].text.strip() #Event Name
dict["Time_Eastern"] = item.find_all("td", {"class":"calendar__time"})[0].text #Time Eastern
impact = item.find_all("td", {"class":"impact"})

for icon in range(0,len(impact)):
dict["Impact"] = impact[icon].find_all("span")[0]['title'].split(' ', 1)[0]
dict["Actual"] = item.find_all("td", {"class":"calendar__actual"})[0].text #Actual Value
dict["Forecast"] = item.find_all("td", {"class":"calendar__forecast"})[0].text #forecasted Value
dict["Previous"] = item.find_all("td", {"class":"calendar__previous"})[0].text # Previous

Set Data frame เหตุผลที่ใช้เวลา Time_Eastern เพราะว่าหากเป็นเวลาไทยเราเรียกมามันจะไม่ตรงกับเวลาจริง ซึ่งหากเราต้องการย้อนดูก็ต้องมาคำนวณเวลาแปลงเป็น Eastern อีกอยู่ดี แล้วทางฝั่งยุโรปมีเรื่อง Daylight saving ด้วย จะได้ตรงกันครับ

df = pandas.DataFrame(data)
df['Currency'] = df['Currency'].str.replace('\n','')
df[["Currency","Event", "Impact","Time_Eastern", "Actual","Forecast", "Previous"]]

แล้วเราจะได้ตารางออกมาแบบนี้ !!!

Set up ! แล้วก็มาถึง Gspread ครับ เราจะเก็บรูปแบบนี้ไว้บน Google sheet กันเลย เริ่มที่โค้ดส่วนแรก อ่านเพิ่มเติมได้จากตรงนี้ https://gspread.readthedocs.io/en/latest/

โดยในส่วนแรกเราต้องทำการเข้าไปขอ Authentic Credentials จากทาง Google developers Console กันก่อน ซึ่งแนะนำให้ทำตามวิธีจากลิงค์ข้างบนเลยครับ เพราะสามารถทำตามได้เลย

หลังจากได้ Key มาแล้ว ให้เราเซฟไว้ด้วยจะมาเป็นนามสกุล .JSON ครับ

อันดับแรก :

pip install gspread 

ในขั้นตอนการเรียก Service ผมแนะนำให้ใช้โค้ดตามนี้เนื่องจากหากใช้โค้ด API เดิมจากหน้าเว็บไซต์จะรันไม่ได้ เพราะตัว API Sheet ได้ทำการอัพเดทไปแล้วครับ

import gspread
from oauth2client.service_account import ServiceAccountCredentials
scope = ['https://www.googleapis.com/auth/spreadsheets'] #ให้ทำการ auth scope เข้า sheet ครับcredentials = ServiceAccountCredentials.from_json_keyfile_name("ชื่อไฟล์ที่เป็น key ที่เซฟมาครับ.json", scope)gc = gspread.authorize(credentials)
sheet = gc.open_by_url('URL ของ Google sheet ที่เราจะส่งข้อมูลขึ้นไปครับ')
wks = sheet.get_worksheet(0) #wks = worksheet

! อย่าลืมเอา Email ที่ได้มาจากไฟล์ .JSON ไปแชร์ที่ Google Sheet แล้วเลือกแบบ edit ด้วยนะครับ

ขั้นตอนนี้ให้เราตั้งตัวแปร df2 ไว้เพื่อเตรียมนำข้อมูลใหม่ไปเพิ่มใน Sheet ครับ

import gspread_dataframe
df2 = gspread_dataframe.get_as_dataframe(wks)

หลังจากที่ได้เรา Data frame ชุดแรกคือ df ที่เราเรียกจาก bs4 เราต้องการจะเก็บบน sheet ก็ส่งคำสั่งไปเก็บไว้ก่อนตามนี้ครับ

gspread_dataframe.set_with_dataframe(wks,df)

จะลองเรียกดูด้วย Code : wks จะแสดงชื่อไฟล์ที่เราตั้งไว้บน google sheet ประมาณนี้ครับ

<Worksheet 'TEST GSPREAD' id:0>

หลังจากขั้นตอนตัดแต่ง Column ตามใจชอบกันแล้ว โดยตัด NaN หรือตั้ง Datetime เสร็จแล้วจับข้อมูลมารวมร่างกันได้เลยครับ df+df2

df2 = df2.append(df,ignore_index=True)

แล้วลองเรียก df2 ดูว่าถูกต้องแบบที่เราต้องการหรือเปล่า หากยังไม่ถูกใจก็แก้ไขไปเรื่อย ซึ่งผมก็ใช้เวลาตรงนี้นานพอสมควร และขอความช่วยเหลือจากเพื่อน ๆ ในทีมจนได้รูปร่างหน้าตาที่ต้องการออกมา ซึ่งหน้า Sheet ที่ผมต้องการก็จะออกมาประมาณนี้ครับ

หลังจากนั้น ก็แชร์ E-mail ให้เพื่อนร่วมงานสามารถเข้ามาติดตามกันได้ตลอด โดยจะตั้ง loopในการดึงอัตโนมัติไว้เลยก็ได้หรือที่ผมทำเพิ่มคือการเก็บ Article จากแหล่งต่าง ๆ เพื่อนำมาประกอบการตัดสินใจเพิ่มอีกด้วย หวังว่าทุกคนจะลองนำไปใช้งานและสนุกกับการใช้ Python ครับ :)

Tanapat Kamsaiin is a data scientist , trader, data analysis, and Quant Model trading system @ AVA advisor.

--

--