电竞比分网-中国电竞赛事及体育赛事平台

分享

Python 爬蟲(chóng) – BeautifulSoup | 菜鳥(niǎo)教程

 wangyong670 2025-08-25 發(fā)布于新疆

Python 爬蟲(chóng) - BeautifulSoup

Python 爬蟲(chóng)(Web Scraping)是指通過(guò)編寫(xiě) Python 程序從互聯(lián)網(wǎng)上自動(dòng)提取信息的過(guò)程。

爬蟲(chóng)的基本流程通常包括發(fā)送 HTTP 請(qǐng)求獲取網(wǎng)頁(yè)內(nèi)容、解析網(wǎng)頁(yè)并提取數(shù)據(jù),然后存儲(chǔ)數(shù)據(jù)。

Python 的豐富生態(tài)使其成為開(kāi)發(fā)爬蟲(chóng)的熱門(mén)語(yǔ)言,特別是由于其強(qiáng)大的庫(kù)支持。

一般來(lái)說(shuō),爬蟲(chóng)的流程可以分為以下幾個(gè)步驟:

  • 發(fā)送 HTTP 請(qǐng)求:爬蟲(chóng)通過(guò) HTTP 請(qǐng)求從目標(biāo)網(wǎng)站獲取 HTML 頁(yè)面,常用的庫(kù)包括 requests
  • 解析 HTML 內(nèi)容:獲取 HTML 頁(yè)面后,爬蟲(chóng)需要解析內(nèi)容并提取數(shù)據(jù),常用的庫(kù)有 BeautifulSoup、lxml、Scrapy 等。
  • 提取數(shù)據(jù):通過(guò)定位 HTML 元素(如標(biāo)簽、屬性、類名等)來(lái)提取所需的數(shù)據(jù)。
  • 存儲(chǔ)數(shù)據(jù):將提取的數(shù)據(jù)存儲(chǔ)到數(shù)據(jù)庫(kù)、CSV 文件、JSON 文件等格式中,以便后續(xù)使用或分析。

本章節(jié)主要介紹 BeautifulSoup,它是一個(gè)用于解析 HTML 和 XML 文檔的 Python 庫(kù),能夠從網(wǎng)頁(yè)中提取數(shù)據(jù),常用于網(wǎng)頁(yè)抓取和數(shù)據(jù)挖掘。


BeautifulSoup

BeautifulSoup 是一個(gè)用于從網(wǎng)頁(yè)中提取數(shù)據(jù)的 Python 庫(kù),特別適用于解析 HTML 和 XML 文件。

BeautifulSoup 能夠通過(guò)提供簡(jiǎn)單的 API 來(lái)提取和操作網(wǎng)頁(yè)中的內(nèi)容,非常適合用于網(wǎng)頁(yè)抓取和數(shù)據(jù)提取的任務(wù)。

安裝 BeautifulSoup

要使用 BeautifulSoup,需要安裝 beautifulsoup4 和 lxml 或 html.parser(一個(gè) HTML 解析器)。

我們可以使用 pip 來(lái)安裝這些依賴:

pip install beautifulsoup4
pip install lxml  # 推薦使用 lxml 作為解析器(速度更快)

如果你沒(méi)有 lxml,可以使用 Python 內(nèi)置的 html.parser 作為解析器。

基本用法

BeautifulSoup 用于解析 HTML 或 XML 數(shù)據(jù),并提供了一些方法來(lái)導(dǎo)航、搜索和修改解析樹(shù)。

BeautifulSoup 常見(jiàn)的操作包括查找標(biāo)簽、獲取標(biāo)簽屬性、提取文本等。

要使用 BeautifulSoup,需要先導(dǎo)入 BeautifulSoup,并將 HTML 頁(yè)面加載到 BeautifulSoup 對(duì)象中。

通常,你會(huì)先用爬蟲(chóng)庫(kù)(如 requests)獲取網(wǎng)頁(yè)內(nèi)容:

實(shí)例

from bs4 import BeautifulSoup
import requests

# 使用 requests 獲取網(wǎng)頁(yè)內(nèi)容
url = 'https://cn.bing.com/' # 抓取bing搜索引擎的網(wǎng)頁(yè)內(nèi)容
response = requests.get(url)

# 使用 BeautifulSoup 解析網(wǎng)頁(yè)
soup = BeautifulSoup(response.text, 'lxml')  # 使用 lxml 解析器
# 解析網(wǎng)頁(yè)內(nèi)容 html.parser 解析器
# soup = BeautifulSoup(response.text, 'html.parser')

獲取網(wǎng)頁(yè)標(biāo)題:

實(shí)例

from bs4 import BeautifulSoup
import requests

# 指定你想要獲取標(biāo)題的網(wǎng)站
url = 'https://cn.bing.com/' # 抓取bing搜索引擎的網(wǎng)頁(yè)內(nèi)容

# 發(fā)送HTTP請(qǐng)求獲取網(wǎng)頁(yè)內(nèi)容
response = requests.get(url)
# 中文亂碼問(wèn)題
response.encoding = 'utf-8'
# 確保請(qǐng)求成功
if response.status_code == 200:
    # 使用BeautifulSoup解析網(wǎng)頁(yè)內(nèi)容
    soup = BeautifulSoup(response.text, 'lxml')
   
    # 查找<title>標(biāo)簽
    title_tag = soup.find('title')
   
    # 打印標(biāo)題文本
    if title_tag:
        print(title_tag.get_text())
    else:
        print("未找到<title>標(biāo)簽")
else:
    print("請(qǐng)求失敗,狀態(tài)碼:", response.status_code)

執(zhí)行以上代碼,輸出標(biāo)題為:

搜索 - Microsoft 必應(yīng)

中文亂碼問(wèn)題

使用 requests 庫(kù)抓取中文網(wǎng)頁(yè)時(shí),可能會(huì)遇到編碼問(wèn)題,導(dǎo)致中文內(nèi)容無(wú)法正確顯示,為了確保能夠正確抓取并顯示中文網(wǎng)頁(yè),通常需要處理網(wǎng)頁(yè)的字符編碼。

自動(dòng)檢測(cè)編碼 requests 通常會(huì)自動(dòng)根據(jù)響應(yīng)頭中的 Content-Type 來(lái)推測(cè)網(wǎng)頁(yè)的編碼,但有時(shí)可能不準(zhǔn)確,此時(shí)可以使用 chardet 來(lái)自動(dòng)檢測(cè)編碼。

實(shí)例

import requests

url = 'https://cn.bing.com/'
response = requests.get(url)

# 使用 chardet 自動(dòng)檢測(cè)編碼
import chardet
encoding = chardet.detect(response.content)['encoding']
print(encoding)
response.encoding = encoding

執(zhí)行以上代碼,輸出為:

utf-8

如果你知道網(wǎng)頁(yè)的編碼(例如 utf-8 或 gbk),可以直接設(shè)置 response.encoding:

response.encoding = 'utf-8'  # 或者 'gbk',根據(jù)實(shí)際情況選擇

查找標(biāo)簽

BeautifulSoup 提供了多種方法來(lái)查找網(wǎng)頁(yè)中的標(biāo)簽,最常用的包括 find() 和 find_all()。

  • find() 返回第一個(gè)匹配的標(biāo)簽
  • find_all() 返回所有匹配的標(biāo)簽

實(shí)例

from bs4 import BeautifulSoup
import requests

# 指定你想要獲取標(biāo)題的網(wǎng)站
url = 'https://www.baidu.com/' # 抓取bing搜索引擎的網(wǎng)頁(yè)內(nèi)容

# 發(fā)送HTTP請(qǐng)求獲取網(wǎng)頁(yè)內(nèi)容
response = requests.get(url)
# 中文亂碼問(wèn)題
response.encoding = 'utf-8'

soup = BeautifulSoup(response.text, 'lxml')

# 查找第一個(gè) <a> 標(biāo)簽
first_link = soup.find('a')
print(first_link)
print("----------------------------")

# 獲取第一個(gè) <a> 標(biāo)簽的 href 屬性
first_link_url = first_link.get('href')
print(first_link_url)
print("----------------------------")

# 查找所有 <a> 標(biāo)簽
all_links = soup.find_all('a')
print(all_links)

輸出結(jié)果類似如下:

<a class="mnav"  name="tj_trnews">新聞</a>
----------------------------
http://news.baidu.com
----------------------------
[<a class="mnav"  name="tj_trnews">新聞</a>, <a class="mnav"  name="tj_trhao123">hao123</a>, <a class="mnav"  name="tj_trmap">地圖</a>, <a class="mnav"  name="tj_trvideo">視頻</a>,

獲取標(biāo)簽的文本

通過(guò) get_text() 方法,你可以提取標(biāo)簽中的文本內(nèi)容:

實(shí)例

from bs4 import BeautifulSoup
import requests

# 指定你想要獲取標(biāo)題的網(wǎng)站
url = 'https://www.baidu.com/' # 抓取bing搜索引擎的網(wǎng)頁(yè)內(nèi)容

# 發(fā)送HTTP請(qǐng)求獲取網(wǎng)頁(yè)內(nèi)容
response = requests.get(url)
# 中文亂碼問(wèn)題
response.encoding = 'utf-8'

soup = BeautifulSoup(response.text, 'lxml')

# 獲取第一個(gè) <p> 標(biāo)簽中的文本內(nèi)容
paragraph_text = soup.find('p').get_text()

# 獲取頁(yè)面中所有文本內(nèi)容
all_text = soup.get_text()
print(all_text)

輸出結(jié)果類似如下:

 百度一下,你就知道           
...

查找子標(biāo)簽和父標(biāo)簽

你可以通過(guò) parent 和 children 屬性訪問(wèn)標(biāo)簽的父標(biāo)簽和子標(biāo)簽:
# 獲取當(dāng)前標(biāo)簽的父標(biāo)簽
parent_tag = first_link.parent

# 獲取當(dāng)前標(biāo)簽的所有子標(biāo)簽
children = first_link.children

實(shí)例

from bs4 import BeautifulSoup
import requests

# 指定你想要獲取標(biāo)題的網(wǎng)站
url = 'https://www.baidu.com/' # 抓取bing搜索引擎的網(wǎng)頁(yè)內(nèi)容

# 發(fā)送HTTP請(qǐng)求獲取網(wǎng)頁(yè)內(nèi)容
response = requests.get(url)
# 中文亂碼問(wèn)題
response.encoding = 'utf-8'

soup = BeautifulSoup(response.text, 'lxml')

# 查找第一個(gè) <a> 標(biāo)簽
first_link = soup.find('a')
print(first_link)
print("----------------------------")

# 獲取當(dāng)前標(biāo)簽的父標(biāo)簽
parent_tag = first_link.parent
print(parent_tag.get_text())

輸出結(jié)果類似如下:

<a class="mnav"  name="tj_trnews">新聞</a>
----------------------------
 新聞 hao123 地圖 視頻 貼吧  登錄   更多產(chǎn)品 

查找具有特定屬性的標(biāo)簽

你可以通過(guò)傳遞屬性來(lái)查找具有特定屬性的標(biāo)簽。

例如,查找類名為 example-class 的所有 div 標(biāo)簽:

# 查找所有 class="example-class" 的 <div> 標(biāo)簽
divs_with_class = soup.find_all('div', class_='example-class')

# 查找具有 id="unique-id" 的 <p> 標(biāo)簽
unique_paragraph = soup.find('p', id='unique-id')

獲取搜索按鈕,id 為 su :

實(shí)例

from bs4 import BeautifulSoup
import requests

# 指定你想要獲取標(biāo)題的網(wǎng)站
url = 'https://www.baidu.com/' # 抓取bing搜索引擎的網(wǎng)頁(yè)內(nèi)容

# 發(fā)送HTTP請(qǐng)求獲取網(wǎng)頁(yè)內(nèi)容
response = requests.get(url)
# 中文亂碼問(wèn)題
response.encoding = 'utf-8'

soup = BeautifulSoup(response.text, 'lxml')

# 查找具有 id="unique-id" 的 <input> 標(biāo)簽
unique_input = soup.find('input', id='su')

input_value = unique_input['value'] # 獲取 input 輸入框的值

print(input_value)

輸出結(jié)果為:

百度一下

高級(jí)用法

CSS 選擇器

BeautifulSoup 也支持通過(guò) CSS 選擇器來(lái)查找標(biāo)簽。

select() 方法允許使用類似 jQuery 的選擇器語(yǔ)法來(lái)查找標(biāo)簽:

# 使用 CSS 選擇器查找所有 class 為 'example' 的 <div> 標(biāo)簽
example_divs = soup.select('div.example')

# 查找所有 <a> 標(biāo)簽中的 href 屬性
links = soup.select('a[href]')

處理嵌套標(biāo)簽

BeautifulSoup 支持深度嵌套的 HTML 結(jié)構(gòu),你可以通過(guò)遞歸查找子標(biāo)簽來(lái)處理這些結(jié)構(gòu):

# 查找嵌套的 <div> 標(biāo)簽
nested_divs = soup.find_all('div', class_='nested')
for div in nested_divs:
    print(div.get_text())

修改網(wǎng)頁(yè)內(nèi)容

BeautifulSoup 允許你修改 HTML 內(nèi)容。

我們可以修改標(biāo)簽的屬性、文本或刪除標(biāo)簽:

實(shí)例

# 修改第一個(gè) <a> 標(biāo)簽的 href 屬性
first_link['href'] = 'http://'

# 修改第一個(gè) <p> 標(biāo)簽的文本內(nèi)容
first_paragraph = soup.find('p')
first_paragraph.string = 'Updated content'

# 刪除某個(gè)標(biāo)簽
first_paragraph.decompose()

轉(zhuǎn)換為字符串

你可以將解析的 BeautifulSoup 對(duì)象轉(zhuǎn)換回 HTML 字符串:

# 轉(zhuǎn)換為字符串
html_str = str(soup)

BeautifulSoup 屬性與方法

以下是 BeautifulSoup 中常用的屬性和方法:

方法/屬性描述示例
BeautifulSoup()用于解析 HTML 或 XML 文檔并返回一個(gè) BeautifulSoup 對(duì)象。soup = BeautifulSoup(html_doc, 'html.parser')
.prettify()格式化并美化文檔內(nèi)容,生成結(jié)構(gòu)化的字符串。print(soup.prettify())
.find()查找第一個(gè)匹配的標(biāo)簽。tag = soup.find('a')
.find_all()查找所有匹配的標(biāo)簽,返回一個(gè)列表。tags = soup.find_all('a')
.find_all_next()查找當(dāng)前標(biāo)簽后所有符合條件的標(biāo)簽。tags = soup.find('div').find_all_next('p')
.find_all_previous()查找當(dāng)前標(biāo)簽前所有符合條件的標(biāo)簽。tags = soup.find('div').find_all_previous('p')
.find_parent()返回當(dāng)前標(biāo)簽的父標(biāo)簽。parent = tag.find_parent()
.find_all_parents()查找當(dāng)前標(biāo)簽的所有父標(biāo)簽。parents = tag.find_all_parents()
.find_next_sibling()查找當(dāng)前標(biāo)簽的下一個(gè)兄弟標(biāo)簽。next_sibling = tag.find_next_sibling()
.find_previous_sibling()查找當(dāng)前標(biāo)簽的前一個(gè)兄弟標(biāo)簽。prev_sibling = tag.find_previous_sibling()
.parent獲取當(dāng)前標(biāo)簽的父標(biāo)簽。parent = tag.parent
.next_sibling獲取當(dāng)前標(biāo)簽的下一個(gè)兄弟標(biāo)簽。next_sibling = tag.next_sibling
.previous_sibling獲取當(dāng)前標(biāo)簽的前一個(gè)兄弟標(biāo)簽。prev_sibling = tag.previous_sibling
.get_text()提取標(biāo)簽內(nèi)的文本內(nèi)容,忽略所有HTML標(biāo)簽。text = tag.get_text()
.attrs返回標(biāo)簽的所有屬性,以字典形式表示。href = tag.attrs['href']
.string獲取標(biāo)簽內(nèi)的字符串內(nèi)容。string_content = tag.string
.name返回標(biāo)簽的名稱。tag_name = tag.name
.contents返回標(biāo)簽的所有子元素,以列表形式返回。children = tag.contents
.descendants返回標(biāo)簽的所有后代元素,生成器形式。for child in tag.descendants: print(child)
.parent獲取當(dāng)前標(biāo)簽的父標(biāo)簽。parent = tag.parent
.previous_element獲取當(dāng)前標(biāo)簽的前一個(gè)元素(不包括文本)。prev_elem = tag.previous_element
.next_element獲取當(dāng)前標(biāo)簽的下一個(gè)元素(不包括文本)。next_elem = tag.next_element
.decompose()從樹(shù)中刪除當(dāng)前標(biāo)簽及其內(nèi)容。tag.decompose()
.unwrap()移除標(biāo)簽本身,只保留其子內(nèi)容。tag.unwrap()
.insert()向標(biāo)簽內(nèi)插入新標(biāo)簽或文本。tag.insert(0, new_tag)
.insert_before()在當(dāng)前標(biāo)簽前插入新標(biāo)簽。tag.insert_before(new_tag)
.insert_after()在當(dāng)前標(biāo)簽后插入新標(biāo)簽。tag.insert_after(new_tag)
.extract()刪除標(biāo)簽并返回該標(biāo)簽。extracted_tag = tag.extract()
.replace_with()替換當(dāng)前標(biāo)簽及其內(nèi)容。tag.replace_with(new_tag)
.has_attr()檢查標(biāo)簽是否有指定的屬性。if tag.has_attr('href'):
.get()獲取指定屬性的值。href = tag.get('href')
.clear()清空標(biāo)簽的所有內(nèi)容。tag.clear()
.encode()編碼標(biāo)簽內(nèi)容為字節(jié)流。encoded = tag.encode()
.is_empty_element檢查標(biāo)簽是否是空元素(例如 <br>、<img> 等)。if tag.is_empty_element:
.is_ancestor_of()檢查當(dāng)前標(biāo)簽是否是指定標(biāo)簽的祖先元素。if tag.is_ancestor_of(another_tag):
.is_descendant_of()檢查當(dāng)前標(biāo)簽是否是指定標(biāo)簽的后代元素。if tag.is_descendant_of(another_tag):

其他屬性

方法/屬性描述示例
.style獲取標(biāo)簽的內(nèi)聯(lián)樣式。style = tag['style']
.id獲取標(biāo)簽的 id 屬性。id = tag['id']
.class_獲取標(biāo)簽的 class 屬性。class_name = tag['class']
.string獲取標(biāo)簽內(nèi)部的字符串內(nèi)容,忽略其他標(biāo)簽。content = tag.string
.parent獲取標(biāo)簽的父元素。parent = tag.parent

其他

方法/屬性描述示例
find_all(string)使用字符串查找匹配的標(biāo)簽。tag = soup.find_all('div', class_='container')
find_all(id)查找指定 id 的標(biāo)簽。tag = soup.find_all(id='main')
find_all(attrs)查找具有指定屬性的標(biāo)簽。tag = soup.find_all(attrs={"href": "http://"})

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購(gòu)買(mǎi)等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多