Python 的簡潔語法和豐富的函式庫使其成為網頁爬蟲的理想工具。本文將探討如何使用 BeautifulSoup 和 Requests 函式庫從網頁中提取資料,同時也將介紹 Selenium 的使用,以應對動態網頁內容的擷取。我們將逐步講解如何傳送 HTTP 請求、解析 HTML 結構、提取目標資料,以及處理分頁和動態內容,並提供實際案例與最佳實務建議,協助您建構高效且合規的網頁爬蟲。
網頁爬蟲技術:使用 BeautifulSoup 與 Requests 進行資料擷取
網頁爬蟲是從網站中提取資料的過程,涉及程式化地存取網頁、下載其內容,並解析資料以提取相關資訊。Python 藉助其強大的函式庫如 BeautifulSoup 和 Requests,使網頁爬蟲變得簡單高效。
為什麼需要網頁爬蟲?
- 資料收集:收集大量資料集進行分析。
- 競爭分析:監控競爭對手的網站。
- 內容聚合:從多個來源收集和聚合內容。
- 自動化:自動化重複的資料收集任務。
設定您的環境
在開始網頁爬蟲之前,您需要設定 Python 環境。
安裝必要的函式庫
# 安裝 BeautifulSoup 和 Requests
pip install beautifulsoup4 requests
匯入函式庫
import requests
from bs4 import BeautifulSoup
使用 Python 理解 HTTP 請求
HTTP(超文字傳輸協定)是網路上資料通訊的基礎。Python 中的 requests 函式庫允許您輕鬆傳送 HTTP 請求。
傳送 GET 請求
# 向網站傳送 GET 請求
response = requests.get('https://example.com')
# 檢查請求是否成功
if response.status_code == 200:
print("請求成功!")
else:
print("請求失敗,狀態碼:", response.status_code)
處理標頭和引數
# 在請求中新增標頭和引數
headers = {'User-Agent': 'Mozilla/5.0'}
params = {'q': 'python 網頁爬蟲'}
response = requests.get('https://example.com/search', headers=headers, params=params)
BeautifulSoup 簡介
BeautifulSoup 是一個用於解析 HTML 和 XML 檔案的 Python 函式庫。它提供了簡單的方法來導航、搜尋和修改解析樹。
建立 BeautifulSoup 物件
# 解析 HTML 內容
soup = BeautifulSoup(response.content, 'html.parser')
# 列印解析後的 HTML
print(soup.prettify())
瀏覽 HTML 樹
# 找到第一個 <h1> 標籤
h1_tag = soup.find('h1')
print("第一個 H1 標籤:", h1_tag.text)
# 找到所有 <a> 標籤
a_tags = soup.find_all('a')
for tag in a_tags:
print("連結:", tag.get('href'))
解析 HTML 和提取資料
BeautifulSoup 提供各種方法從 HTML 檔案中提取資料。
提取文字
# 從特定標籤中提取文字
title = soup.find('title')
print("標題:", title.text)
提取屬性
# 從標籤中提取屬性
img_tag = soup.find('img')
print("圖片來源:", img_tag.get('src'))
使用 CSS 選擇器
# 使用 CSS 選擇器查詢元素
articles = soup.select('div.article')
for article in articles:
print("文章標題:", article.find('h2').text)
處理分頁和多個頁面
許多網站使用分頁來顯示大量資料。您需要透過迭代多個頁面來處理這種情況。
範例:爬取多個頁面
base_url = 'https://example.com/page/{page_number}'
for page_number in range(1, 6):
url = base_url.format(page_number=page_number)
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
# 從每個頁面提取資料
articles = soup.select('div.article')
for article in articles:
print("文章標題:", article.find('h2').text)
內容解密:
此範例程式碼展示如何處理網站的分頁結構。首先,我們定義了一個基本的 URL 範本 base_url,其中包含一個佔位符 {page_number} 用於替換不同的頁碼。然後,我們使用 for 迴圈遍歷第 1 到第 5 頁,動態生成每個頁面的 URL。對每個頁面傳送 GET 請求後,我們使用 BeautifulSoup 解析 HTML 內容,並提取所有具有 article 類別的 <div> 元素。最後,我們列印出每個文章的標題。
使用 Selenium 爬取動態內容
有些網站使用 JavaScript 動態載入內容。Selenium,一個瀏覽器自動化工具,可以用來處理這種情況。
安裝 Selenium
# 安裝 Selenium
pip install selenium
使用 Selenium 爬取動態內容
from selenium import webdriver
# 設定 WebDriver
driver = webdriver.Chrome()
# 開啟網頁
driver.get('https://example.com')
# 等待動態內容載入
driver.implicitly_wait(10)
# 使用 BeautifulSoup 提取資料
soup = BeautifulSoup(driver.page_source, 'html.parser')
articles = soup.select('div.article')
for article in articles:
print("文章標題:", article.find('h2').text)
# 關閉 WebDriver
driver.quit()
內容解密:
此範例程式碼展示如何使用 Selenium 處理動態載入的網頁內容。首先,我們匯入 webdriver 並設定 Chrome 瀏覽器的 WebDriver。然後,開啟目標網頁並等待最多 10 秒讓動態內容載入完成。接著,我們將瀏覽器的頁面原始碼傳遞給 BeautifulSoup 進行解析,並提取所有具有 article 類別的 <div> 元素。最後,列印出每個文章的標題並關閉 WebDriver。
最佳實踐和倫理考量
最佳實踐
- 尊重 Robots.txt:檢查網站的 robots.txt 檔案以瞭解允許的操作。
- 使用標頭:透過設定標頭模擬真實使用者行為。
- 速率限制:透過在請求之間新增延遲避免使伺服器過載。
倫理考量
- 合法合規:確保您的爬蟲活動符合法律和倫理標準。
- 資料隱私:尊重使用者隱私,不爬取敏感資訊。
真實範例和案例研究
範例 1:爬取新聞頭條
url = 'https://example-news.com'
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
headlines = soup.select('h2.headline')
for headline in headlines:
print("頭條:", headline.text)
範例 2:爬取產品價格
url = 'https://example-store.com/products'
response = requests.get(url)
soup = BeautifulSoup(response.content, 'html.parser')
products = soup.select('div.product')
for product in products:
name = product.find('h3').text
price = product.find('span', class_='price').text
print(f"產品:{name}, 價格:{price}")
使用Selenium自動化網頁互動的技術
Selenium是一種強大的工具,能夠實作網頁瀏覽器的自動化控制。它支援多種程式語言,包括Python,並且可以與多種網頁瀏覽器(如Chrome、Firefox和Edge)相容。Selenium的應用範圍包括網頁測試、資料擷取和網頁爬蟲等。
為什麼選擇Selenium?
- 跨瀏覽器測試:能夠在不同的瀏覽器上測試網頁應用程式。
- 網頁爬蟲:能夠從需要互動的網站中擷取資料。
- 自動化測試:能夠自動執行重複性的測試任務。
設定Selenium
要開始使用Selenium,需要安裝Selenium套件並下載適合您瀏覽器的WebDriver。
安裝Selenium
pip install selenium
下載WebDriver
- Chrome:ChromeDriver
- Firefox:GeckoDriver
範例程式碼
# 從selenium函式庫匯入webdriver模組
from selenium import webdriver
# 設定Chrome驅動程式的路徑
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
# 開啟指定的網頁
driver.get('https://www.example.com')
# 關閉瀏覽器
driver.quit()
內容解密:
from selenium import webdriver:匯入Selenium的webdriver模組,用於控制瀏覽器。driver = webdriver.Chrome(executable_path='/path/to/chromedriver'):初始化Chrome瀏覽器的webdriver,並指定ChromeDriver的路徑。driver.get('https://www.example.com'):開啟指定的網址。driver.quit():關閉瀏覽器並結束webdriver程式。
基本的網頁互動
Selenium允許您與網頁進行互動,例如導航到URL、點選連結和填寫表單。
範例程式碼
# 從selenium函式庫匯入webdriver模組
from selenium import webdriver
# 設定Chrome驅動程式的路徑
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
# 開啟指定的網頁
driver.get('https://www.example.com')
# 點選連結文字為「About Us」的元素
link = driver.find_element_by_link_text('About Us')
link.click()
# 關閉瀏覽器
driver.quit()
內容解密:
driver.get('https://www.example.com'):開啟指定的網址。link = driver.find_element_by_link_text('About Us'):根據連結文字找到對應的元素。link.click():模擬點選該連結的操作。
處理網頁元素
Selenium提供了多種方法來定位和與網頁元素(如按鈕、文字方塊和下拉式選單)進行互動。
範例程式碼
# 從selenium函式庫匯入webdriver模組
from selenium import webdriver
# 設定Chrome驅動程式的路徑
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
# 開啟指定的網頁
driver.get('https://www.example.com')
# 根據ID找到元素
element = driver.find_element_by_id('element_id')
# 根據類別名稱找到元素
element = driver.find_element_by_class_name('element_class')
# 根據XPath找到元素
element = driver.find_element_by_xpath('//div[@class="element_class"]')
# 關閉瀏覽器
driver.quit()
內容解密:
driver.find_element_by_id('element_id'):根據元素的ID屬性定位元素。driver.find_element_by_class_name('element_class'):根據元素的類別名稱定位元素。driver.find_element_by_xpath('//div[@class="element_class"]'):使用XPath表示式定位元素。
自動提交表單
自動提交表單涉及填寫表單欄位並提交表單。
範例程式碼
# 從selenium函式庫匯入webdriver模組
from selenium import webdriver
# 設定Chrome驅動程式的路徑
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
# 開啟指定的網頁
driver.get('https://www.example.com/form')
# 填寫文字欄位
text_field = driver.find_element_by_name('username')
text_field.send_keys('your_username')
# 選擇下拉式選單選項
dropdown = driver.find_element_by_id('dropdown_id')
dropdown.send_keys('Option 1')
# 提交表單
submit_button = driver.find_element_by_id('submit_button')
submit_button.click()
# 關閉瀏覽器
driver.quit()
內容解密:
text_field.send_keys('your_username'):在文字欄位中輸入指定文字。dropdown.send_keys('Option 1'):選擇下拉式選單中的指定選項。submit_button.click():模擬點選提交按鈕的操作。
處理警告和彈出視窗
Selenium能夠處理在網頁互動過程中出現的警告和彈出視窗。
範例程式碼
# 從selenium函式庫匯入webdriver模組
from selenium import webdriver
# 設定Chrome驅動程式的路徑
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
# 開啟指定的網頁
driver.get('https://www.example.com')
# 觸發警告
driver.find_element_by_id('alert_button').click()
# 處理警告
alert = driver.switch_to.alert
alert.accept()
# 關閉瀏覽器
driver.quit()
內容解密:
driver.find_element_by_id('alert_button').click():點選觸發警告的元素。alert = driver.switch_to.alert:切換到警告框。alert.accept():接受警告框(例如點選「確定」按鈕)。
與框架和視窗互動
Selenium允許您在框架和視窗之間切換,以實作複雜的網頁互動。
範例程式碼
# 從selenium函式庫匯入webdriver模組
from selenium import webdriver
# 設定Chrome驅動程式的路徑
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
# 開啟指定的網頁
driver.get('https://www.example.com')
# 切換到框架
driver.switch_to.frame('frame_id')
# 在框架內執行操作
frame_element = driver.find_element_by_id('frame_element_id')
frame_element.click()
# 切換回主內容
driver.switch_to.default_content()
# 關閉瀏覽器
driver.quit()
內容解密:
driver.switch_to.frame('frame_id'):切換到指定的框架。frame_element.click():在框架內點選指定的元素。driver.switch_to.default_content():切換回主內容區域。
自動執行JavaScript
Selenium能夠在瀏覽器中執行JavaScript程式碼。
範例程式碼
# 從selenium函式庫匯入webdriver模組
from selenium import webdriver
# 設定Chrome驅動程式的路徑
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
# 開啟指定的網頁
driver.get('https://www.example.com')
# 執行JavaScript程式碼,彈出警告框顯示「Hello, World!」
driver.execute_script('alert("Hello, World!");')
# 關閉瀏覽器
driver.quit()
內容解密:
driver.execute_script('alert("Hello, World!");'):執行指定的JavaScript程式碼,在此範例中彈出一個警告框。
擷取螢幕截圖和下載檔案
Selenium能夠擷取網頁的螢幕截圖並自動下載檔案。
範例程式碼
from selenium import webdriver
def main():
# 設定Chrome驅動程式的路徑並開啟瀏覽器
driver = webdriver.Chrome(executable_path='/path/to/chromedriver')
try:
# 開啟指定的網頁
driver.get('https://www.example.com')
# 擷取螢幕截圖並儲存為檔案「screenshot.png」
driver.save_screenshot('screenshot.png')
# 找到下載連結並點選,下載檔案
download_link = driver.find_element_by_link_text('Download')
download_link.click()
finally:
# 確保無論如何都會關閉瀏覽器,防止資源洩漏
driver.quit()
if __name__ == "__main__":
main()
內容解密:
save_screenshot方法:用於將當前瀏覽器視窗的內容儲存為圖片檔案。引數為檔案路徑,如'screenshot.png'表示將截圖儲存為當前目錄下的screenshot.png。find_element_by_link_text方法:用於根據連結的顯示文字來定位元素。例如,引數'Download'表示查詢顯示文字為 “Download” 的超連結元素。click方法:用於模擬點選操作。當在找到的下載連結元素上呼叫此方法時,會觸發下載操作,就像使用者手動點選該連結一樣。
高階的網頁互動技術
高階技術包括處理動態內容、使用無頭瀏覽器以及與其他工具整合等。
範例程式碼(無頭模式)
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
def main():
# 設定Chrome選項
chrome_options = Options()
chrome_options.add_argument("--headless") # 以無頭模式執行
# 初始化WebDriver並開啟瀏覽器(無頭模式)
driver = webdriver.Chrome(executable_path='/path/to/chromedriver', options=chrome_options)
try:
# 開啟目標網址
driver.get('https://www.example.com')
# 在無頭模式下進行操作,例如點選某個元素
element = driver.find_element_by_id('element_id')
element.click()
# 可以進行其他操作,如擷取網頁內容等
page_source = driver.page_source
print(page_source)
finally:
# 確保無論如何都會關閉瀏覽器,防止資源洩漏
driver.quit()
if __name__ == "__main__":
main()
內容解密:
chrome_options.add_argument("--headless"):將 Chrome 瀏覽器設定為無介面模式執行,即在背景執行,不顯示視窗。webdriver.Chrome(options=chrome_options):初始化 Chrome WebDriver 時,將組態好的選項傳入,使瀏覽器以無介面模式啟動。find_element_by_id和click方法的使用與有介面模式相同,用於定位元素並模擬點選操作。
這種無介面模式特別適合自動化測試、資料抓取等背景任務,能夠節省系統資源並提高執行效率。