本篇文章是使用bs4中的BeautifulSoup和requests解析網(wǎng)頁和獲取數(shù)據(jù)????
??前言
為了更深入的學(xué)習(xí)爬蟲,今天來了解下bs4的使用和實(shí)踐,當(dāng)然解析網(wǎng)頁不止只有bs4的BeautifulSoup可以做到,還有xpath語法和正則表達(dá)式。本期是初步的了解BeautifulSoup模塊的使用,歡迎初學(xué)者學(xué)習(xí)本期內(nèi)容。
一、??bs4中的BeautifulSoup
BeautifulSoup庫是Python編程語言中的一款第三方庫,主要用于解析HTML和XML文檔。這個(gè)庫能夠?qū)?fù)雜的HTML或XML數(shù)據(jù)轉(zhuǎn)換為樹形結(jié)構(gòu)(即DOM樹),讓開發(fā)者能夠以更簡單的方式來遍歷、搜索和操作這些結(jié)構(gòu)化的數(shù)據(jù)。
bs4的四種解析方式
:
解析器 | 使用方法 | 優(yōu)勢 | 劣勢 |
---|---|---|---|
python標(biāo)準(zhǔn)庫 | soup = BeautifulSoup(htmlt, ‘html.parser’) | python內(nèi)置標(biāo)準(zhǔn)庫;執(zhí)行速度適中 | python2.x或者python3.2x前的版本中文文檔容錯(cuò)能力差 |
lxml HTML解析器 | soup = BeautifulSoup(html, ‘lxml’) | 速度快;文檔容錯(cuò)能力強(qiáng) | 需要安裝c語言庫 |
lxml XML解析器 | soup = BeautifulSoup(html, ‘xml’) | 速度快;唯一支持XML的解析器 | 需要安裝c語言庫 |
html5lib | soup = BeautifulSoup(html, ‘html5lib’) | 最好的容錯(cuò)性;以瀏覽器的方式解析文檔;生成HTML5格式的文檔;不依賴外部擴(kuò)展庫 | 速度慢 |
二、??bs4的語法
- 獲取全部的單個(gè)標(biāo)簽:
soup.find_all('標(biāo)簽')
- 獲取擁有指定屬性的標(biāo)簽:
soup.find_all('標(biāo)簽',屬性的鍵值對)
soup.find_all('標(biāo)簽',attrs={鍵值對1,鍵值對2})
注意
:attrs是存儲(chǔ)的是字典,里面可以包含html的多個(gè)屬性
- 獲取多個(gè)指定屬性的標(biāo)簽:
soup.find_all('標(biāo)簽',屬性的鍵值對1,屬性的鍵值對2)
如果在獲取時(shí),出現(xiàn)python關(guān)鍵字與屬性沖突時(shí),在獲取的時(shí)候添加一個(gè)下劃線 ' _ '
,例如:
soup.find_all('div',class_='position')
- 獲取標(biāo)簽屬性值:
先鎖定標(biāo)簽
alist=soup.find_all('a')
- 方法1:
通過下標(biāo)方式提取
for a in alist:
href=a['href']
print(href)
- 方法2:
利用attrs參數(shù)提取
for a in alist:
href=a.attrs['href']
print(href)
-
獲取標(biāo)簽內(nèi)的文本信息:
使用string方法
# 獲取html的所有div標(biāo)簽,從第二個(gè)開始
divs=soup.find_all('div')[1:]
# 利用循環(huán)輸出每個(gè)標(biāo)簽
for div in divs:
# 只提取標(biāo)簽下的字符串
a=div.find_all('a')[0].string
# 提取整個(gè)div下的字符串
divs=soup.find_all('div')[1:]
for div in divs:
infos=list(div.stripped_strings) # stripped_strings方法是刪除列表中的制表符,例如: "\n,\t"等
三、??內(nèi)容實(shí)踐
爬取的網(wǎng)頁鏈接:https://www.autohome.com.cn/news/1/#liststart
1. 確定想要爬取的內(nèi)容
在此以爬?。呵拔屙摰模?biāo)題、更新時(shí)間和頁面部分顯示的詳細(xì)內(nèi)容)
2. 分析網(wǎng)頁
首頁內(nèi)容,這里要注意的是這個(gè)網(wǎng)頁鏈接,可以從第一頁到第三頁的鏈接對比
仔細(xì)查看后,只有這個(gè)/news/
后的數(shù)字發(fā)生了變化,所以我們只要做一個(gè)循環(huán)數(shù)字的方式更改內(nèi)容就可以
https://www.autohome.com.cn/news/1/#liststart
https://www.autohome.com.cn/news/2/#liststart
https://www.autohome.com.cn/news/3/#liststart
內(nèi)容實(shí)施:
urls = [] # 定義一個(gè)列表存放每頁的鏈接
for i in range(1, 6):
url = f"https://www.autohome.com.cn/news/{i}/#liststart"
urls.append(url)
# print(urls)
3. 獲取數(shù)據(jù)分析
- 觀察html標(biāo)簽內(nèi)容
- 獲取網(wǎng)頁的標(biāo)簽信息,發(fā)現(xiàn)這些標(biāo)簽都在div標(biāo)簽中的ul標(biāo)簽里面
- 對比標(biāo)簽,發(fā)現(xiàn)每個(gè)內(nèi)容都是使用的相同標(biāo)簽
- 代碼
# 導(dǎo)包
from bs4 import BeautifulSoup
import requests
# 設(shè)置請求頭
url = 'https://www.autohome.com.cn/news/'
headers = {
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/123.0.0.0 Safari/537.36 Edg/123.0.0.0"
}
# 利用循環(huán)讀取前5分頁
urls = [] # 定義一個(gè)列表存放每頁的鏈接
for i in range(1, 6):
url = f"https://www.autohome.com.cn/news/{i}/#liststart"
urls.append(url)
# print(urls)
# 定義兩個(gè)列表 news存放字典數(shù)據(jù)
news = []
for url in urls:
# 利用try……except語句獲取每頁,如果某頁讀取不了,則繼續(xù)讀取下一頁
try:
response = requests.get(url, headers=headers)
content = response.content.decode('gbk') # 在網(wǎng)頁上查看編碼格式
# print(content)
# 實(shí)例化BeautifulSoup對象
soup = BeautifulSoup(content, 'html.parser')
# print(soup)
# divs=soup.find_all('div',class_="article-pic")
uls = soup.find_all('ul', class_="article")
for ul in uls:
# 獲取標(biāo)題
title = list(ul.find_all('h3'))
# 獲取更新日期
times = list(ul.find_all('span', class_="fn-left"))
# 獲取內(nèi)容
profiles = list(ul.find_all('p'))
# print(times,title,profiles)
# 提取標(biāo)簽內(nèi)的字符串和使用zip打包在一起
for title, times, profiles in zip(title, times, profiles):
title = title.string
times = times.string
profiles = profiles.string
# 將數(shù)據(jù)存放在字典中
car_news = {
"title": title,
"times": times,
"profiles": profiles,
}
news.append(car_news)
except:
continue
print(news)
- 輸出結(jié)果
??總結(jié)
這里需要注意的是使用bs4語句獲取的標(biāo)簽內(nèi)容是bs4的類型,不是列表類型,所以使用了強(qiáng)制轉(zhuǎn)換成列表【list()
】.
拓展:
在Python爬蟲中,即使代碼看起來沒有明顯語法錯(cuò)誤,爬取的數(shù)據(jù)仍然可能為空,這通常與以下因素有關(guān):文章來源:http://www.zghlxwxcb.cn/news/detail-857127.html
- 目標(biāo)網(wǎng)站結(jié)構(gòu)改變:
如果爬蟲是基于HTML結(jié)構(gòu)編寫的,而目標(biāo)網(wǎng)站進(jìn)行了改版或更新,原有的選擇器(如XPath或CSS Selector)可能不再有效,導(dǎo)致找不到預(yù)期的數(shù)據(jù)。- 動(dòng)態(tài)加載內(nèi)容:
網(wǎng)頁上的數(shù)據(jù)可能是通過JavaScript動(dòng)態(tài)加載的,直接爬取HTML源代碼可能無法獲取這些數(shù)據(jù)。此時(shí)需要分析網(wǎng)頁加載邏輯,使用如Selenium、Pyppeteer等工具模擬瀏覽器行為,或者通過分析Ajax請求來間接獲取數(shù)據(jù)。- 反爬策略:
目標(biāo)網(wǎng)站可能啟用了反爬蟲策略,比如Cookies驗(yàn)證、User-Agent限制、IP封鎖、驗(yàn)證碼、登錄驗(yàn)證等。這時(shí),需要針對這些策略進(jìn)行相應(yīng)的處理,比如設(shè)置更真實(shí)的User-Agent、使用代理IP池、處理驗(yàn)證碼或模擬登錄。- 請求參數(shù)不正確:
請求頭信息(headers)、cookies、POST數(shù)據(jù)等參數(shù)可能需要特殊配置才能獲取數(shù)據(jù),如果缺少必要參數(shù)或參數(shù)不正確,服務(wù)器可能不會(huì)返回有效數(shù)據(jù)。- 網(wǎng)絡(luò)問題:
即使代碼看似沒問題,網(wǎng)絡(luò)連接不穩(wěn)定或服務(wù)器端出現(xiàn)問題也可能導(dǎo)致無法獲取數(shù)據(jù)。- 解析邏輯錯(cuò)誤:
數(shù)據(jù)解析環(huán)節(jié)可能出現(xiàn)問題,例如正則表達(dá)式匹配不正確,或者在解析HTML或JSON時(shí)引用了不存在的鍵或?qū)傩浴?/li>- API調(diào)用權(quán)限或頻率限制:
若爬取的是API接口,可能存在調(diào)用頻率限制、API密鑰失效或沒有必要的授權(quán)。- 數(shù)據(jù)緩存問題:
如果爬蟲有緩存機(jī)制并且緩存了錯(cuò)誤的結(jié)果,新的爬取可能會(huì)直接讀取緩存而非從服務(wù)器獲取新數(shù)據(jù)。
要解決這個(gè)問題,可以從以下幾個(gè)步驟入手:文章來源地址http://www.zghlxwxcb.cn/news/detail-857127.html
- 檢查并確認(rèn)請求網(wǎng)址是否正確且能夠正常訪問;
- 使用開發(fā)者工具查看網(wǎng)頁加載過程,確認(rèn)數(shù)據(jù)是如何加載和呈現(xiàn)的;
- 檢查請求頭和請求體是否符合目標(biāo)網(wǎng)站的要求;
- 檢查解析代碼邏輯,特別是提取數(shù)據(jù)的部分;
- 檢測網(wǎng)絡(luò)狀況以及是否有反爬措施,調(diào)整爬蟲策略;
- 對于動(dòng)態(tài)加載內(nèi)容,確保相應(yīng)腳本能夠正確執(zhí)行或模擬;
- 針對可能出現(xiàn)的API限制,合理安排請求間隔,遵循網(wǎng)站的使用協(xié)議。
到了這里,關(guān)于python爬蟲小案例——汽車之家的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!