使用python,爬取網(wǎng)頁(yè)評(píng)論(實(shí)例:豆瓣《都挺好》)
python的第三方庫(kù)豐富了python的功能,今天就用python的第三方庫(kù)requests和bs4這兩個(gè)庫(kù)來(lái)實(shí)現(xiàn)對(duì)一個(gè)網(wǎng)頁(yè)的爬取
操作環(huán)境
python3.7.2
requests庫(kù)
bs4庫(kù)
requests庫(kù)和bs4庫(kù)下載
如果你的電腦只用python3的版本使用以下方式下載:
pip install requests
pip install bs4
如果你的電腦中python3和python2的版本都存在:
python3 -m pip install
python2 -m pip install
這一步是最基本的,如果沒(méi)有安裝成功請(qǐng)先自行百度解決。
目標(biāo)網(wǎng)站:
https://book.douban.com/subject/20492971/comments/hot
先查看網(wǎng)絡(luò)源代碼,觀察網(wǎng)頁(yè)源代碼的結(jié)構(gòu)和我們要爬取的內(nèi)容,這次我們要爬取的是用戶名、用戶評(píng)論、有用數(shù),評(píng)論的星數(shù)和日期。
通過(guò)觀察我們發(fā)現(xiàn)我們所需的內(nèi)容主要出現(xiàn)在這一部分:
Sofia
2013-06-30
《都挺好》=《回家》。強(qiáng)勢(shì)母親帶來(lái)的家庭矛盾:
懦弱的兒子+強(qiáng)勢(shì)的女兒。
縱容的寵愛(ài)是一種慢性毒藥,慢慢侵蝕人的奮斗、拼搏精神和生存能力。
“窮養(yǎng)”的女兒被逼著成長(zhǎng),凌厲干練,
卻失去了愛(ài)的能力——無(wú)論是愛(ài)人還是愛(ài)己。父母之愛(ài)要的就是一個(gè)平衡的點(diǎn)。
所以下一步就是如何將其爬取出來(lái)
爬取過(guò)程
將目標(biāo)網(wǎng)頁(yè)的所有內(nèi)容爬取下來(lái),再進(jìn)行下一步的篩選
def getHTMLText(url):
try:
r = requests.get(url,timeout=30)
r.raise_for_status()
r.enconding = "utf-8"
return r.text
except:
return ""
現(xiàn)在我們要觀察我們要爬去的內(nèi)容具體在什么位置
soup.find_all()函數(shù)可以實(shí)現(xiàn)篩選的目的;
我們可以看到我們要的主要內(nèi)容都在標(biāo)簽span class="comment-info“
使用soup.find_all(“span”, ‘comment-info’)來(lái)篩選:
def fillBookdata(Bookdata,html):
soup = BeautifulSoup(html, 'html.parser')
commmentinfo = soup.find_all("span", 'comment-info')
pattern = re.compile('user-stars allstar(\d+) rating')
p = re.findall(pattern, str(commmentinfo))
comments = soup.find_all('span', 'short')
for i in range(len(commmentinfo)):
Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])
這里使用了正則表達(dá)式需要使用re庫(kù)
正則表達(dá)式的使用可以參考別的文章,在此不做介紹。
現(xiàn)在寫一個(gè)輸出函數(shù)來(lái)顯示我們的爬取結(jié)果
def printList(Bookdata,num):
for i in range(num):
u = Bookdata[i]
print("序號(hào):{}\n用戶名:{}\n評(píng)論內(nèi)容:{}\n評(píng)分:{}星\n".format(i + 1,u[0], u[1],int(int(u[2])/10)))
運(yùn)行結(jié)果如下:
與我們的爬取結(jié)果最比較可以發(fā)現(xiàn)我們目前爬取的內(nèi)容都是正確的。
但這個(gè)只是第一頁(yè)的內(nèi)容如果我們要連續(xù)的爬取呢?
通過(guò)觀察我們可以發(fā)現(xiàn)連續(xù)的網(wǎng)頁(yè)存在一定的規(guī)律:
這是第一頁(yè)https://book.douban.com/subject/20492971/comments/hot
這是第二頁(yè)https://book.douban.com/subject/20492971/comments/hot?p=2
這是第三頁(yè)https://book.douban.com/subject/20492971/comments/hot?p=3
由此我們可以改變輸出函數(shù)即可:
for i in range(3):
print('第',i+1,'頁(yè)')
main('https://book.douban.com/subject/20492971/comments/hot?p='+str(i+1))
在運(yùn)行一下:
第二頁(yè)出錯(cuò)了!!!為什么呢?
具體錯(cuò)誤:
Traceback (most recent call last):
File "E:\pythonwork\4-3-1.py", line 62, in
main('https://book.douban.com/subject/20492971/comments/hot?p='+str(i+1))
File "E:\pythonwork\4-3-1.py", line 53, in main
fillBookdata(uinfo1,html)
File "E:\pythonwork\4-3-1.py", line 38, in fillBookdata
Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])
IndexError: list index out of range
再百度完錯(cuò)誤后,我們查看一下第二頁(yè)的源代碼,我們可以發(fā)現(xiàn)不是所用的用戶都給了星數(shù):
下面的用戶就沒(méi)有給出評(píng)價(jià),所以儲(chǔ)存星數(shù)的列表的內(nèi)容并沒(méi)有達(dá)到20個(gè),也就是后面的星數(shù)為空,所以彈出來(lái)錯(cuò)誤;這個(gè)問(wèn)題目前我還沒(méi)有很好的解決方式,希望各位小主獻(xiàn)計(jì)獻(xiàn)策。
以下是我的不完美的解決方式:
def fillBookdata(Bookdata,html):
soup = BeautifulSoup(html, 'html.parser')
commmentinfo = soup.find_all("span", 'comment-info')
pattern = re.compile('user-stars allstar(\d+) rating')
p = re.findall(pattern, str(commmentinfo))
comments = soup.find_all('span', 'short')
for i in range(len(commmentinfo)):
#設(shè)置異常處理機(jī)制,發(fā)現(xiàn)空值的情況人為的給其加一個(gè)值0
try:
Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])
except IndexError:
#添加一個(gè)0值
Bookdata.append([commmentinfo[i].a.string, comments[i].string, '0'])
#pass
但這樣的添加方式不好,不能正確的匹配到了沒(méi)有給星數(shù)的用戶。如果有更完美的方式我會(huì)在后續(xù)的文章中發(fā)布。
附上現(xiàn)在的代碼:
import requests
from bs4 import BeautifulSoup
import bs4
import re
def getHTMLText(url):
try:
r = requests.get(url,timeout=30)
r.raise_for_status()
r.enconding = "utf-8"
return r.text
except:
return ""
def fillBookdata(Bookdata,html):
soup = BeautifulSoup(html, 'html.parser')
commmentinfo = soup.find_all("span", 'comment-info')
pattern = re.compile('user-stars allstar(\d+) rating')
p = re.findall(pattern, str(commmentinfo))
comments = soup.find_all('span', 'short')
for i in range(len(commmentinfo)):
#設(shè)置異常處理機(jī)制,發(fā)現(xiàn)空值的情況人為的給其加一個(gè)值0
try:
Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])
except IndexError:
#添加一個(gè)0值
Bookdata.append([commmentinfo[i].a.string, comments[i].string, '0'])
#pass
'''
def fillBookdata(Bookdata,html):
soup = BeautifulSoup(html, 'html.parser')
commmentinfo = soup.find_all("span", 'comment-info')
pattern = re.compile('user-stars allstar(\d+) rating')
p = re.findall(pattern, str(commmentinfo))
comments = soup.find_all('span', 'short')
for i in range(len(commmentinfo)):
Bookdata.append([commmentinfo[i].a.string, comments[i].string, p[i]])
'''
def printList(Bookdata,num):
for i in range(num):
u = Bookdata[i]
print("序號(hào):{}\n用戶名:{}\n評(píng)論內(nèi)容:{}\n評(píng)分:{}星\n".format(i + 1,u[0], u[1],int(int(u[2])/10)))
def main(url):
uinfo1 = []
'''
url = 'https://book.douban.com/subject/20492971/comments/hot'
'''
html = getHTMLText(url)
fillBookdata(uinfo1,html)
printList(uinfo1,20)
'''
main('https://book.douban.com/subject/20492971/comments/hot')
'''
for i in range(3):
print('第',i+1,'頁(yè)')
main('https://book.douban.com/subject/20492971/comments/hot?p='+str(i+1))
當(dāng)然我們還有發(fā)布時(shí)間和有用數(shù)未實(shí)現(xiàn),這兩個(gè)都可以通過(guò)使用正則表達(dá)式來(lái)實(shí)現(xiàn)(有機(jī)會(huì)各位小主可以認(rèn)真學(xué)習(xí)一下正則表達(dá)式)
pattern1=re.compile('>(\d+)<')
#匹配時(shí)間的正則表達(dá)式
pattern2 = re.compile('>(\d{4}-\d{1,2}-\d{1,2})<')
修改一下輸出函數(shù)即可實(shí)現(xiàn)一下的效果:
如有不足,還望見(jiàn)諒。希望各位小主給出更好的建議。
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
