今天的想的是加強一下python3爬蟲的技巧,以爬糗事百科的段子作為練習(xí)目標(biāo),以下是爬蟲經(jīng)歷疏尿。
1.導(dǎo)包
主要導(dǎo)兩類包,一個是網(wǎng)絡(luò)請求包urllib易桃,另一個是正則表達式包re
import urllib.request,urllib.error
import re
2.構(gòu)建url
我要爬的是糗事百科的24小時里的段子褥琐,它的網(wǎng)址是
于是我的url構(gòu)成如下,pageNum表示頁數(shù)
url='http://www.qiushibaike.com/hot/page/' + str(pageNum)
3.增加報頭晤郑,偽裝瀏覽器
如果不加報頭直接抓取源代碼似乎會報錯敌呈,所以我偽裝了一下嚼鹉,打開chrome進入糗事百科,再右鍵打開檢查->network->request headers驱富,
把User-Agent復(fù)制了
user_agent='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
Headers={'User-Agent':user_agent}
4.構(gòu)建正則表達式
這是核心的地方锚赤,我一開始寫的時候每一個標(biāo)簽都去匹配,然后正則表達式寫得很長很長褐鸥,最后還不知哪里錯了打印不出結(jié)果线脚,后來請教了別人寫正則表達式的方法,發(fā)現(xiàn)只需要匹配核心的標(biāo)簽即可叫榕,其他無關(guān)的標(biāo)簽一律用.*?匹配浑侥。
先看看我要抓取的內(nèi)容吧
像上圖這樣就是一條段子,由于圖片不可能顯示晰绎,所以即使是有圖片的段子我也只顯示文字寓落,那么我要匹配的內(nèi)容有:用戶的名字,段子的內(nèi)容荞下,“好笑”前面的數(shù)字伶选,“好笑”這兩個字,“評論”前面的數(shù)字尖昏,“評論”這兩個字
那么我就要在源代碼中找到這些內(nèi)容仰税,通過查看源代碼發(fā)現(xiàn),一個段子的代碼是下面這種格式
<div class="article block untagged mb15" id='qiushi_tag_117121225'>
<div class="author clearfix">
<a href="/users/30591370/" target="_blank" rel="nofollow">

</a>
<a href="/users/30591370/" target="_blank" title="逆風(fēng)的單車">
<h2>逆風(fēng)的單車</h2>
</a>
</div>
<div class="content">
小時候喜歡摸堂弟頭抽诉,喊他小不點陨簇,如今當(dāng)兵回來的他,喜歡摸著我的頭迹淌,喊我“老 部(不)長”河绽,還特么時不時的摔我一跤!0η浴耙饰!
</div>
<div class="stats">
<span class="stats-vote"><i class="number">3760</i> 好笑</span>
<span class="stats-comments">
<span class="dash"> · </span>
<a href="/article/117121225" data-share="/article/117121225" id="c-117121225" class="qiushi_comments" target="_blank">
<i class="number">32</i> 評論
</a>
</span>
</div>
我們要的東西的位置一目了然,首先是用戶的名字:
<h2>逆風(fēng)的單車</h2>
然后是段子的內(nèi)容:
<div class="content">
小時候喜歡摸堂弟頭句携,喊他小不點榔幸,如今當(dāng)兵回來的他,喜歡摸著我的頭矮嫉,喊我“老 部(不)長”削咆,還特么時不時的摔我一跤!4浪瘛拨齐!
</div>
接著是“好笑”
<span class="stats-vote"><i class="number">3760</i> 好笑</span>
最后是評論
<a href="/article/117121225" data-share="/article/117121225" id="c-117121225" class="qiushi_comments" target="_blank">
<i class="number">32</i> 評論</a>
所以我們可以寫出正則表達式
pattern=re.compile('<h2>(.*?)</h2>.*?<div class="content">(.*?)</div>.*?<i class="number">(.*?)</i> (.*?)</span>.*?<i class="number">(.*?)</i>(.*?)</a>',re.S)
注:因為是順序匹配,所以“好笑”和評論只需要用<i class="number">匹配就好昨寞,其他雜七雜八的東西一律用.*?代替
5.寫出請求
剩下的就是使用urllib來抓取源代碼匹配后輸出了
try:
request=urllib.request.Request(url,headers=Headers)
response=urllib.request.urlopen(request).read().decode('utf-8')
items=re.findall(pattern,response)# for item in items:
print(item[0],item[1],item[2],item[3],item[4],item[5])
except urllib.error.URLError as e:
if hasattr(e,'code'):
print(e.code)
if hasattr(e,'reason'):
print(e.reason)
完整的代碼是
import urllib.request,urllib.error
import re
pageNum=1
url='http://www.qiushibaike.com/hot/page/' + str(pageNum)
user_agent='Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36' Headers={'User-Agent':user_agent}
pattern=re.compile('<h2>(.*?)</h2>.*?<div class="content">(.*?)</div>.*?<i class="number">(.*?)</i> (.*?)</span>.*?<i class="number">(.*?)</i>(.*?)</a>',re.S)
try:
request=urllib.request.Request(url,headers=Headers)
response=urllib.request.urlopen(request).read().decode('utf-8')
items=re.findall(pattern,response)
for item in items:
print(item[0],item[1],item[2],item[3],item[4],item[5])
except urllib.error.URLError as e:
if hasattr(e,'code'):
print(e.code)
if hasattr(e,'reason'):
print(e.reason)
這樣就能抓到啦瞻惋。