一文帶您理解Selenium 和 BeautifulSoup:掌握數據抓取的核心技術
近期開發了一個數據抓取/數據格式化(指定網站內容)的小工具,起初設想使用 requests 和正則表達式的組合來實現,然而實際操作后發現無法順利抓取數據。于是我轉而嘗試 requests 搭配 BeautifulSoup,但問題依舊,頁面采用動態加載且有反爬機制,必須模擬瀏覽器行為才能獲取數據。最后,經過多次調整,最終選擇了 Python 驅動的 Selenium 方案,并結合正則表達式來格式化數據,成功實現了抓取任務。
接下來,將探討使用 Selenium、BeautifulSoup 和 HTML 結構進行網頁抓取的基礎知識。無論您是有抱負的數據科學家,還是只是想擴展您的技術技能,這些知識都將成為您網頁抓取之旅的基礎。
HTML:Web 的支柱
HTML(超文本標記語言)是創建網頁的標準語言。它由一系列定義網站結構、布局和內容的元素組成。
這些元素由標簽表示,例如 <p> 表示段落、<h1> 表示標題、<a> 表示超鏈接。通過了解這些標簽的組織方式,您可以識別在網頁抓取過程中要提取的相關內容。
每個 HTML 文件都由構成其底層結構的幾個基本組件組成。這些組件以嵌套的層次結構組織,文檔的內容包含在這些標簽中。
<!DOCTYPE html>
<html>
<head>
<title>您的頁面標題</title>
</head>
<body>
<!-- 您的內容放在此處 -->
</body>
</html>
- <!DOCTYPE html>:此聲明定義所使用的 HTML 文檔類型和版本。它可幫助瀏覽器了解如何正確呈現頁面。
- <html>:這是頁面的根元素,它包含文檔的所有其他元素。
- <head>:head 元素包含有關文檔的元信息。
- <title>:title元素指定網頁的標題,顯示在瀏覽器的標題欄或選項卡中。
- <body>:body元素包含網頁的實際內容,如文本、圖像和多媒體。
除了構成 HTML 文件基本結構的標簽外,還有許多其他標簽用于在網頁上創建不同類型的內容。以下是您會遇到的一些最常見的 HTML 標簽:
- <h1>至<h6>:這些是標題標簽,用于在內容中創建標題和副標題。<h1>是最大和最重要的,而是<h6>最小和最不重要的。
- <p>:段落標簽用于創建文本段落。它會自動在段落前后添加邊距,從而在文本塊之間提供清晰的分隔。
- <a>:錨標記用于創建超鏈接,使用戶可以在網頁之間導航。該href屬性指定鏈接的目標 URL。
- <ul>和<ol>:這些標簽分別用于創建無序列表(項目符號)和有序列表(編號)。列表中的每個項目都包含在一個<li>標簽中。
- <table>:table 標簽用于創建表格,以行和列的形式顯示數據。它通常與其他標簽(如<tr>(表格行)、<th>(表格標題)和<td>(表格數據單元格))一起使用。
每個 HTML 元素可以具有各種屬性,這些屬性可提供附加信息或修改其行為。網頁抓取中最常用的一些屬性是class、id和href。和通常class都id用于定位和獲取感興趣的信息。href用于瀏覽不同的頁面。
- class:該class屬性允許您將一個或多個 CSS 類分配給 HTML 元素
<p class="highlighted important" >
本段落class屬性有兩個類:“highlighted”和“important”。
</p>
- id:該id屬性用于唯一標識 HTML 文檔中的元素。每個id值在整個文檔中都必須是唯一的。
<div id = "main-content" >
此div具有唯一ID:“main-content”
。</div>
- href:該href屬性主要與 (anchor) 標簽一起使用<a>,指定超鏈接的目標 URL。當用戶點擊鏈接時,瀏覽器將導航到指定的 URL。
<a >
訪問百度
</a>
網絡數據抓取主要有三種方式:
- 靜態抓取:這種方式僅解析 HTML,忽略 JavaScript。它不需要瀏覽器即可從服務器提取網頁,獲取的內容就是頁面源代碼中看到的靜態部分。通過提供的 URL,您可以直接獲取 HTML 結構進行剪切和解析。這也是它被稱為“靜態抓取”的原因——只需獲取并處理服務器返回的靜態頁面內容。
- API 抓取:如今很多網站的架構是 API + JS 的組合。通過分析頁面結構,可以找到 API 地址和請求方法,直接向服務器發送請求,獲取結構化的 JSON 數據。這種方式最為簡便,因為返回的數據是格式化的json 或xml 數據。
- 動態抓取:這種方式使用瀏覽器,可以讀取通過 JavaScript 生成或修改的內容。簡而言之,動態抓取模擬真實用戶操作——像用戶一樣發送輸入、改變頁面或點擊按鈕。有時,還需要自動化瀏覽器操作來獲取特定內容。對于此類任務,通常需要使用 Selenium WebDriver 來模擬用戶行為。
這三種方式各有優劣,選擇哪種方式取決于目標網站的技術架構和防爬策略。
使用 BeautifulSoup 進行靜態網頁抓取
Beautifulsoup是一個使用 HTML/XML 解析器并將網頁/html/xml 轉換為標簽、元素、屬性和值的樹的 Python 庫。
安裝BeautifulSoup
向想要抓取的網頁的 URL 發送一個 HTTP GET 請求,服務器將返回包含 HTML 內容的響應,使用 Python 的 requests 庫來請求;使用BeautifulSoup加載解析html。
from bs4 import BeautifulSoup
import requests
url='https://bot.sannysoft.com/'
html_content = requests.get(url).text
soup = BeautifulSoup(html_content, "html")
print(soup.prettify())
可以通過 .find([element_tag]) 方法輕松從 HTML 結構中提取出我們感興趣的內容——用于查找單個元素;如果有多個元素,可以使用 .findAll([element_tag]) 方法。
table_ele=soup.find('table')
tres=table_ele.findAll('tr')
for tr in tres:
tdes=tr.findAll('td')
if len(tdes)>1:
print(tdes[0].text,':',tdes[1].text)
使用 Selenium 進行動態網頁抓取
Selenium 用于自動化網頁應用程序操作。它允許您像人類用戶一樣打開瀏覽器并執行任務,例如點擊按鈕和在網站上搜索特定信息。
安裝Selenium和驅動,需要一個驅動程序來與瀏覽器進行交互。
- 安裝 Selenium:在命令提示符或終端中運行以下命令:pip install selenium
- 下載驅動程序:需要瀏覽器的驅動程序,讓 Selenium 能夠與瀏覽器交互。建議使用chrome,檢查您的 Google Chrome 版本,然后在 https://developer.chrome.com/docs/chromedriver/downloads?hl=zh-cn下載對應的 Chromedriver。
下面是一個簡單的示例:
import subprocess
import threading
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.common.by import By
import time
def openChrome():
cmd = '"C:\Program Files\Google\Chrome\Application\chrome.exe" ' \
'--remote-debugging-port=9222 ' \
'--user-data-dir="d:\selenium\ChromeProfile" ' \
' --disable-popup-blocking --disable-gpu --safebrowsing-disable-download-protection '
sub_chrome_process = subprocess.Popen(cmd, shell=True)
thread = threading.Thread(target=openChrome)
thread.start()
time.sleep(2)
print(f"{openChrome =}")
def getDriver():
chrome_options = Options()
chrome_options.add_argument('--ignore-certificate-errors')
chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")
driver = webdriver.Chrome(optinotallow=chrome_options)
"""params = {
"behavior": "allow",
"downloadPath": download_dir # 設置新的下載路徑
}
driver.execute_cdp_cmd("Page.setDownloadBehavior", params)
driver.execute_cdp_cmd("Security.setIgnoreCertificateErrors", {"ignore": True})"""
return driver
driver =getDriver()
driver.get("https://bot.sannysoft.com/")
print("*"*50)
table_ele=driver.find_element(By.TAG_NAME,"table")
for tr_ele in table_ele.find_elements(By.TAG_NAME,"tr"):
tdes_ele=tr_ele.find_elements(By.TAG_NAME,'td')
if len(tdes_ele)>1:
print(tdes_ele[0].text.replace('\n',''),":",tdes_ele[1].text)
print("*"*50)
scroll_step = 200 # 每次滾動的像素
pause_time = 0.3 # 每次滾動后的等待時間(秒)
current_height = driver.execute_script("return document.body.scrollHeight") # 獲取當前頁面總高度
# 逐步向下滾動
for j in range(0, current_height, scroll_step):
driver.execute_script(f"window.scrollBy(0, {scroll_step});")
time.sleep(pause_time)
這段代碼的邏輯和步驟如下:
1.導入必要的庫:
subprocess:用于在 Python 中啟動新進程。
threading:用于創建和管理線程。
selenium.webdriver:用于與瀏覽器進行交互。
time:用于時間延遲。
2.定義 openChrome 函數:
構造一個命令行字符串 cmd,用于啟動 Google Chrome 瀏覽器,并指定一些啟動選項,注意開啟遠程模式:--remote-debugging-port=9222:開啟遠程調試,允許其他程序(如 Selenium)連接到這個端口。
使用 subprocess.Popen 啟動 Chrome 瀏覽器進程。
3.創建并啟動線程:
使用 threading.Thread 創建一個新線程,目標是運行 openChrome 函數。
啟動該線程,并在啟動后等待 2 秒,以確保 Chrome 瀏覽器啟動完成。
4.定義 getDriver 函數:
創建一個 Options 對象,配置 Chrome 的啟動選項。
添加忽略證書錯誤的選項:chrome_options.add_argument('--ignore-certificate-errors')。
設置調試地址,使 Selenium 能夠連接到已啟動的 Chrome 實例:chrome_options.add_experimental_option("debuggerAddress", "127.0.0.1:9222")。
使用配置的選項創建 Chrome WebDriver 實例并返回。
5.獲取 WebDriver:
調用 getDriver 函數獲取 WebDriver 并訪問指定的 URL(這里是一個示例網頁 "https://bot.sannysoft.com/")。
6.打印表格數據:
使用 find_element 和 find_elements 方法找到網頁中的 <table> 元素及其子元素 <tr> 和 <td>。
遍歷表格的每一行,如果該行中有多個單元格(<td>),則打印第一個和第二個單元格的文本內容。
7.滾動頁面:
設置每次滾動的像素和等待時間。
獲取當前頁面的總高度。
使用 execute_script 方法逐步向下滾動頁面,直到達到頁面底部。
通過這段代碼,您可以實現自動化瀏覽器操作,抓取網頁上的表格數據,并進行頁面滾動,以獲取更多信息。
特別注意的如果是直接打開的chrome 瀏覽器的話(driver =webdriver.Chrome()) ,WebDriver 標記為True,有較多的網站防爬取判斷,被網站攔截掉,可以直接先開啟遠程模式打開chrome ,然后創建dirver連接到debuggerAddress 上驅動chrome 。
以下是實踐過程中點滴總結:
- 網站數據爬取是全棧的技術活,需要了解HTTP、HTML、Python、Selenium、BeautifulSoup、正則表達式、驗證碼識別等。
- 從網站進行數據爬取和解析本質上可以理解網頁的非格式化數據逆向為格式化數據的過程;不同完整需要不同的方式和策略,特別是網站防爬設置、流量控制,需要控制速率、模擬一些真人操作的一些行為。
- 內容的解析和格式化才是最具挑戰性的工作,特別是解析文檔類的數據,正則表達式的功底是需要的。
網站數據爬取是一項全棧技術,涉及 HTTP、HTML、Python、Selenium、BeautifulSoup 和正則表達式等工具。成功抓取依賴于對網頁結構的理解、繞過防爬機制及流量控制。解析與格式化是其中最具挑戰的環節,特別是文檔類數據的處理,需要扎實的正則表達式能力。