
- Python 網路爬蟲教程
- Python 網路爬蟲 - 首頁
- 簡介
- Python 入門
- 用於網路爬蟲的 Python 模組
- 網路爬蟲的合法性
- 資料提取
- 資料處理
- 處理影像和影片
- 處理文字
- 爬取動態網站
- 爬取基於表單的網站
- 處理驗證碼
- 使用爬蟲進行測試
- Python 網路爬蟲資源
- Python 網路爬蟲 - 快速指南
- Python 網路爬蟲 - 資源
- Python 網路爬蟲 - 討論
Python 網路爬蟲 - 動態網站
在本章中,讓我們學習如何在動態網站上執行網路爬蟲以及所涉及的概念。
簡介
網路爬蟲是一項複雜的任務,如果網站是動態的,複雜性就會成倍增加。根據聯合國全球網路可訪問性審計,超過 70% 的網站本質上是動態的,它們依賴 JavaScript 來實現其功能。
動態網站示例
讓我們來看一個動態網站的示例,並瞭解為什麼它難以爬取。這裡我們將以從名為 http://example.webscraping.com/places/default/search 的網站搜尋為例。但我們如何才能說這個網站是動態的呢?可以透過以下 Python 指令碼的輸出判斷,該指令碼將嘗試從上面提到的網頁抓取資料 -
import re import urllib.request response = urllib.request.urlopen('http://example.webscraping.com/places/default/search') html = response.read() text = html.decode() re.findall('(.*?)',text)
輸出
[ ]
以上輸出顯示,示例爬蟲未能提取資訊,因為我們嘗試查詢的 <div> 元素為空。
從動態網站抓取資料的方法
我們已經看到,爬蟲無法從動態網站抓取資訊,因為資料是使用 JavaScript 動態載入的。在這種情況下,我們可以使用以下兩種技術從依賴動態 JavaScript 的網站抓取資料 -
- 反向工程 JavaScript
- 渲染 JavaScript
反向工程 JavaScript
稱為反向工程的過程將非常有用,並讓我們瞭解網頁如何動態載入資料。
為此,我們需要為指定的 URL 點選“檢查元素”選項卡。接下來,我們將點選“網路”選項卡以查詢對該網頁發出的所有請求,包括具有“/ajax”路徑的 search.json。除了透過瀏覽器或透過“網路”選項卡訪問 AJAX 資料外,我們也可以藉助以下 Python 指令碼來實現 -
import requests url=requests.get('http://example.webscraping.com/ajax/search.json?page=0&page_size=10&search_term=a') url.json()
示例
以上指令碼允許我們使用 Python json 方法訪問 JSON 響應。類似地,我們可以下載原始字串響應,並使用 python 的 json.loads 方法載入它。我們藉助以下 Python 指令碼執行此操作。它基本上會透過搜尋字母“a”並迭代 JSON 響應的結果頁面來抓取所有國家/地區。
import requests import string PAGE_SIZE = 15 url = 'http://example.webscraping.com/ajax/' + 'search.json?page={}&page_size={}&search_term=a' countries = set() for letter in string.ascii_lowercase: print('Searching with %s' % letter) page = 0 while True: response = requests.get(url.format(page, PAGE_SIZE, letter)) data = response.json() print('adding %d records from the page %d' %(len(data.get('records')),page)) for record in data.get('records'):countries.add(record['country']) page += 1 if page >= data['num_pages']: break with open('countries.txt', 'w') as countries_file: countries_file.write('n'.join(sorted(countries)))
執行以上指令碼後,我們將獲得以下輸出,並且記錄將儲存在名為 countries.txt 的檔案中。
輸出
Searching with a adding 15 records from the page 0 adding 15 records from the page 1 ...
渲染 JavaScript
在上一節中,我們對網頁進行了反向工程,瞭解了 API 的工作原理以及如何使用它在一個請求中檢索結果。但是,在進行反向工程時,我們可能會遇到以下困難 -
有時網站可能非常複雜。例如,如果網站是使用高階瀏覽器工具(如 Google Web Toolkit (GWT))建立的,則生成的 JS 程式碼將是機器生成的,難以理解和反向工程。
一些更高級別的框架(如 React.js)可以透過抽象已經很複雜的 JavaScript 邏輯來使反向工程變得困難。
解決上述困難的辦法是使用瀏覽器渲染引擎,該引擎解析 HTML、應用 CSS 格式並執行 JavaScript 以顯示網頁。
示例
在本例中,為了渲染 Java Script,我們將使用一個熟悉的 Python 模組 Selenium。以下 Python 程式碼將藉助 Selenium 渲染網頁 -
首先,我們需要從 selenium 中匯入 webdriver,如下所示 -
from selenium import webdriver
現在,提供我們根據需要下載的 web driver 的路徑 -
path = r'C:\\Users\\gaurav\\Desktop\\Chromedriver' driver = webdriver.Chrome(executable_path = path)
現在,提供我們希望在現在由我們的 Python 指令碼控制的 web 瀏覽器中開啟的 url。
driver.get('http://example.webscraping.com/search')
現在,我們可以使用搜索工具箱的 ID 將元素設定為選中。
driver.find_element_by_id('search_term').send_keys('.')
接下來,我們可以使用 java 指令碼將選擇框內容設定為如下 -
js = "document.getElementById('page_size').options[1].text = '100';" driver.execute_script(js)
以下程式碼行顯示搜尋已準備好點選網頁 -
driver.find_element_by_id('search').click()
下一行程式碼顯示它將等待 45 秒以完成 AJAX 請求。
driver.implicitly_wait(45)
現在,為了選擇國家/地區連結,我們可以使用 CSS 選擇器,如下所示 -
links = driver.find_elements_by_css_selector('#results a')
現在可以提取每個連結的文字以建立國家/地區列表 -
countries = [link.text for link in links] print(countries) driver.close()