以往做一些網頁爬蟲或自動化的事時,通常都是透過 wget/curl 去抓一些靜態網頁的 HTML,再配合 cookie 做一些事情。這樣不專業的爬蟲,其實也爬了很多年了,應該可以應付 80% 的需求吧。但很明顯的問題,就是沒辦法處理動態網頁,也就是有用上 JavaScript 的網頁。
什麼是動態網頁
所謂的動態就是當你在瀏覽網頁時,網頁本身的內容會被 JavaScript 的程式修改。如果你用 wget 去把這個網頁下載下來,因為沒執行 JavaScript,所以它的內容都是靜態固定的。這樣在一些利用 JavaScript 做動態查詢的頁面上,用 wget 抓下來的頁面往往是沒有真正想要的資料。
那以後不需要 WGET 爬蟲了嗎
動態爬蟲雖好,但就是速度慢吃的資源多。動態爬蟲實際上是載入真正的瀏覽器去抓取網頁的內容,這些瀏覽器由於功能都很齊,都是很肥大的。所以載入的時間久,也比較耗資源。如果只是需要靜態內容,建議還是用傳統的 WGET 就好了。
開始吧!Python Selenium 套件
我們這邊講的動態爬蟲,其實就是利用 Python Selenium 這個套件再配合上 Chrome / Firefox 的 Webdriver,就可以操控真正的瀏覽器來進行爬蟲。
而 Webdriver 是指另外獨立用來操控 Chrome / Firefox 的程式,由 Google / Mozilla 自行開發的。而 Python Selenium 便是透過他們提供的標準化介面來操控瀏覽器進行動作。Chrome 與 Firefox 的 webdriver 分別可以在其官方網頁下載。
安裝 Selenium 套件
本文用的是 Python 2.7.15,用 pip 直接安裝就可以了。
1 |
pip install selenium |
安裝 Pyinstaller 套件
由於我們希望把這個動態爬蟲的程式,弄的跟 wget 一樣可以單獨執行,我們也需要這個 Python –> EXE 的打包套件。
1 |
pip install pyinstaller |
下載 WEB Driver
Windows
如果是 Windows,會建議使用 Chrome ,因為 Firefox 我一直試不成功。為避免將來版本更新連結遺失,我已經將 Chrome 的 Web Driver 2.45 放置在這。要用 Chrome Driver,記得一定要裝 Chrome 的瀏覽器才行用喔~~ ChromeDriver 官網
Linux
Linux 的話,建議就用 Firefox 比較方便。因為大部份的 Distribution 都有 Firefox 了,不過版本需要 56+ 以上才行,這點請注意。Firefox WebDriver 官網 。Firefox 的 driver 叫做 Geckodriver 這點請注意,不要以為連錯地方了。
Python Selenium 的 WGET-Like 爬蟲程式
下面就是完成一個簡單的 WGET-Like 的程式,把JavaScript處理後的原始碼抓下,輸出到畫面。
Selenium 可以完全的操控一個瀏覽器,所以其功能其實很全面,這邊我們還是用到比較簡單的功能,只抓取網頁處理過後(Rendered)的原始碼,這樣就足夠了。Selenium 還可以使用諸如,找 Tag, 模擬點按鈕, 開多個分頁,這些功能我沒使用到就不介紹了。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# -*- coding:utf-8 -*- import os import sys import time from selenium import webdriver option = webdriver.ChromeOptions() option.add_argument('headless') option.add_argument("user-agent=Firefox Gecko") driver = webdriver.Chrome(chrome_options=option) if len(sys.argv) < 2: print "Need URL" sys.exit(1) driver.get(sys.argv[1]) time.sleep(5) print driver.page_source.encode("utf-8") driver.quit() |
行8: 指定 Chrome 用無畫面啟動,如果沒這行的話,就會真的看到跑出一個 Chrome 的視窗。這對爬蟲沒有必要,所以就不需顯示。
行9: 指定在瀏覽網站,要使用的 Agent 身份。會做這項設置,是因為部份 (PCHxxe)網站,會阻擋 Chrome Headless 的 Agent,只好假裝自己是 Firefox。
行14: 開始抓取第一個參數指定的網址。
行15: 行14結束後,代表動態網頁所需的資源都抓下來了,但JavaScript可能還沒執行完。所以這邊等待5秒,給它機會執行一下,讓其進行必要的動作。
行16: 將最後的網頁原始碼印出
執行程式
把上面的程式碼儲存為cwget.py後,在我們執行程式前,要把 Chrome Driver (chromedriver.exe) 和 .py 放在一起,python 執行期會自己呼叫 chromedriver.exe。
1 |
python cwget.py "你的網址" > all |
這樣抓取的結果,就會被存放在 all 檔案裡面了。執行時,會有些錯誤訊息,若抓取的結果無誤,可以不用理會。
以上面的 PCHOME 商品為例,若以一般的 wget 抓取的話,價格的部份都不會顯示出來。需要用透過 web driver 的這種方式,才可以取到真正的價格。
轉換成獨立程式
wget 因為不能執行 JavaScript,導致有點弱。所以我們可以把,這支 Python 程式轉換成一支獨立稱為 cwget 的程式,這樣要使用上也比較方便。
1 2 |
pyinstaller -F --add-binary chromedriver.exe;. cwget.py copy dist\cwget.exe . |
這樣一支名為 cwget.exe 的檔案,就會放在跟 cwget.py 同一個地方了。這樣以後帶著 cwget.exe 到哪都可以用,就不用再進行上面煩鎖的步驟了。當然當然…電腦上一定要有安裝 Chrome 瀏覽器的才可執行。