如題。最近在研究Telegram Bot API,雖然讀過文件知道許多語言都已經有不少第三方框架支援,基於某些應用目的不想被框架綁住,所以打算自己寫。然後我就耗了整整兩天,嘗試如何讓部署在Heroku上的Bot能順利使用headless browser擷取到我要的數據…。說也奇怪,本機執行是沒問題的,但在遠端主機就是一直丟出Timeout Error,原來遠端主機控制Chrome訪問目標網頁的時候總是遭遇某DDoS Protection服務所阻擋,但經過一番嘗試目前仍是應對不了這個情況,耗了好幾天…於是學到了windows.navigator.webdriver這個參數。
*假設Heroku APP已建立。
Add Config Vars & Buildpacks
在APP的Setting頁面,設定以下兩個環境變數:1
2CHROMEDRIVER_PATH = /app/.chromedriver/bin/chromedriver
GOOGLE_CHROME_BIN = /app/.apt/usr/bin/google-chrome
在APP的Setting頁面,設定以下兩個buildpack:1
2https://github.com/heroku/heroku-buildpack-google-chrome
https://github.com/heroku/heroku-buildpack-chromedriver
Code
程式的部分,Chrome driver的參數會使用到上述所設定的環境變數。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18import os
from selenium import webdriver
def get_chrome():
op = webdriver.ChromeOptions()
op.binary_location = os.environ.get("GOOGLE_CHROME_BIN")
op.add_argument("--headless")
op.add_argument("--disable-dev-shm-usage")
op.add_argument("--no-sandbox")
'''
# avoid detection 好孩子先不要 ^.<
op.add_argument('--disable-infobars')
op.add_experimental_option('useAutomationExtension', False)
op.add_experimental_option("excludeSwitches", ["enable-automation"])
'''
return webdriver.Chrome(executable_path=os.environ.get("CHROMEDRIVER_PATH"), options=op)
Deploy
然後就可以進行部署使用了,Heroku APP會需要安裝許多依賴套件而增加100+MB的使用空間。
透過APP bash測試從證交所擷取上市股票代號一覽表⬇︎
Ref.
*Running ChromeDriver with Python Selenium on Heroku
*Selenium 官方文件
Note
關於動態網頁資料擷取的小技巧:雖然Selenium WebDriverWait提供explicit waits可等待指定頁面元素載入,但實際上並沒有這麼順利,不過這也是讓我覺得學習web crawler有趣的地方(儘管有時候很頭疼😖)。有時候會發生指定元素確實在頁面上載入完成了,但內容卻是空空如也,又或許是我慧根不夠用不好text_to_be_present_in_element,試了半天還是抓不到我要的數據。哭啊,我就是要擷取內容文字咩!只好換個方式等待:
1 | from selenium.webdriver.support.ui import WebDriverWait |