返回文章列表

Python網頁爬蟲使用BeautifulSoup與Requests

本文介紹如何使用 Python 搭配 BeautifulSoup 和 Requests 函式庫進行網頁爬蟲,涵蓋 HTTP 請求、HTML 解析、資料提取、分頁處理、動態內容爬取以及 Selenium 的應用,提供實用的程式碼範例和最佳實務建議,讓您快速上手網頁資料擷取。

網頁開發 資料科學

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_idclick 方法的使用與有介面模式相同,用於定位元素並模擬點選操作。

這種無介面模式特別適合自動化測試、資料抓取等背景任務,能夠節省系統資源並提高執行效率。