注:(此篇為切換Markdown編輯器調(diào)整了格式重發(fā)的……強(qiáng)迫癥盛险,原來用富文本編輯器寫的太丑了)
今天第一次嘗試用python寫爬蟲费什,在w3shcool學(xué)習(xí)了一下XPath碍岔,用來找結(jié)點(diǎn)獲取內(nèi)容琐旁。過程中遇到幾個小問題,在這里記錄一下并分享給其他初學(xué)者窿锉。本文以爬取糗事百科為例枢赔,這里用的是python2.7倦始。
出現(xiàn)的問題:
- socket.error: [Errno 10054]
- xpath尋找結(jié)點(diǎn)的相對路徑的寫法
糗事百科是一個很容易爬的網(wǎng)站王浴,不需要登錄脆炎。熱門段子的URL是:http://www.qiushibaike.com/hot/page/2/
發(fā)送請求獲取html源碼
直接發(fā)送請求獲取網(wǎng)頁內(nèi)容就好了,page后面的數(shù)字可以用來翻頁氓辣。我們先來試一試直接發(fā)送請求并輸出response的內(nèi)容秒裕。注意請求要設(shè)置headers的內(nèi)容,可以審查元素查看需要設(shè)置的內(nèi)容筛婉。
# -*- coding:utf-8 -*-
import urllib
import urllib2
page=1
url='http://www.qiushibaike.com/hot/page/'+str(page)
user_agent='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36'
headers={'User-Agent':user_agent}
request=urllib2.Request(url,headers=headers)
response=urllib2.urlopen(request)
str_html= response.read()
response.close()
print str_html
運(yùn)行沒有問題簇爆,成功輸出了網(wǎng)頁源碼內(nèi)容。這里筆者出現(xiàn)一個疏忽爽撒,一開始因?yàn)闆]有close掉response,以至于遠(yuǎn)端主機(jī)重置了鏈接响蓉,出現(xiàn)socket.error: [Errno 10054] 硕勿。可能出現(xiàn)該錯誤的還有其他原因枫甲,具體可以參考這篇:python socket 超時設(shè)置 errno 10054
用xpath解析并找到目標(biāo)結(jié)點(diǎn)
我們先嘗試從簡單的開始源武,把當(dāng)前頁面的所有段子的作者名字爬下來輸出扼褪。首先先審查元素,看看頁面的結(jié)構(gòu)粱栖。
id="content-left"
的div里面,段子有共同的特點(diǎn)class="article block untagged mb15"
那我們先獲取所有段子的整個div結(jié)點(diǎn)
tree=html.fromstring(str_html)
nodes=tree.xpath('//div[@id="content-left"]/div[@class="article block untagged mb15"]')
xpath的語法可以參考w3shcool里的XPath 教程闹究,或者其他資料幔崖。
然后我們繼續(xù)看段子的內(nèi)容結(jié)構(gòu),如下圖:
了解了結(jié)構(gòu)我們可以進(jìn)行提取名字了价认。
tree=html.fromstring(str_html)
nodes=tree.xpath('//div[@id="content-left"]/div[@class="article block untagged mb15"]')
for node in nodes:
res_author=node.xpath('//div[@class="author clearfix"]/a[2]/h2')[0].text
print res_author
對于之前找到的每個段子結(jié)點(diǎn)嗅定,我們再找到class="author clearfix"
的子div,再找到第二個a標(biāo)簽下的h2并獲取其text內(nèi)容用踩,即可渠退。但事實(shí)上上圖是一個錯誤的寫法,我們先運(yùn)行一下看結(jié)果脐彩。
于是拥坛,我又測試了一下(下圖),符合我的猜測尘分,但可能是巧合猜惋,所以暫時先這么理解,如果有懂的同學(xué)看到這篇文章培愁,希望可以給我講解一下著摔。
從上圖結(jié)果看,用“//”果然可以從整個文檔中找到所有的段子作者定续,所以之前的代碼為什么會對所有的段子都輸出同一個作者呢谍咆,(猜測)是因?yàn)槊看窝h(huán)都從整個文檔找了一遍禾锤,而每次都是輸出下標(biāo)為[0]的作者名字,當(dāng)然就是一樣的摹察。
而修改后恩掷,變成了每個段子結(jié)點(diǎn)下的相對尋址,對于每個段子只有一個作者供嚎,所以下標(biāo)為[0]的結(jié)果就是該條段子的作者名字了黄娘。
爬取所有段子的主要信息(作者,內(nèi)容查坪,點(diǎn)贊和評論數(shù))
既然作者名字會爬寸宏,其他的文字信息也類似,都是用相對路徑的寫法找到偿曙。直接上完整代碼:(本文只簡單實(shí)現(xiàn)爬取文字內(nèi)容氮凝,沒有爬取圖片望忆。)
# -*- coding:utf-8 -*-
from lxml import html
import urllib
import urllib2
page=1
url='http://www.qiushibaike.com/hot/page/'+str(page)user_agent='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.110 Safari/537.36'
headers={'User-Agent':user_agent}
request=urllib2.Request(url,headers=headers)
response=urllib2.urlopen(request)
str_html= response.read()
response.close()
tree=html.fromstring(str_html)
nodes=tree.xpath('//div[@id="content-left"]/div[@class="article block untagged mb15"]')
#循環(huán)對每個段子結(jié)點(diǎn)進(jìn)行輸出
for node in nodes:
#解析每個段子
res_author=node.xpath('div[@class="author clearfix"]/a[2]/h2')[0].text
content=node.xpath('a[@class="contentHerf"]/div[@class="content"]/span') [0].text
num_vote=node.xpath('div[@class="stats"]/span[@class="stats-vote"]/i')[0].text
num_comments=node.xpath('div[@class="stats"]/span[@class="stats-comments"]/a[@class="qiushi_comments"]/i')[0].text
#輸出指定內(nèi)容
print u"作者:"+res_author
print "---------------------------------------------------------"
print u"內(nèi)容:"+content
print "---------------------------------------------------------"
print u"點(diǎn)贊:"+num_vote+u",評論:"+num_comments+"\n"
運(yùn)行結(jié)果截圖: