使用Python語言作為工具進行web數(shù)據(jù)爬取是一件很輕松的事隔节。正則表達式則是一種可以高速匹配文本的操作,當正則表達式與Python相結(jié)合時遂赠,也會摩擦出不一樣的火花宁否。
本文將通過一個簡單的爬蟲案例對簡書頁面進行數(shù)據(jù)爬取,運用requests模塊與re模塊铸磅。抓取簡書首頁1000條文章鏈接與標題骤素。
依賴庫
該案例需要導入以下3個Python模塊。
- requests
- fake_useragent
- re
其中愚屁, requests和fake_useragent并不是Python標準庫的模塊,使用前可以通過pip安裝一下痕檬。
pip install requests -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
pip install fake_useragent -i http://pypi.douban.com/simple --trusted-host pypi.douban.com
當然霎槐,requests也可以使用urllib代替,主要用來請求頁面并返回數(shù)據(jù)梦谜。
fake_useragent的功能為自動生成一個user-agent丘跌,當然也可使用自己瀏覽器的user-agent。
re模塊則是Python標準庫的正則模塊唁桩,在本案例中用于過濾數(shù)據(jù)闭树,關(guān)于re模塊的使用可以參考筆者之前的文章。
import re
import requests
import fake_useragent
尋找接口
筆者推薦使用Chrome瀏覽器進行接口排查荒澡。
首先進入在Chrome中進入簡書首頁报辱,按f12進入開發(fā)者工具狀態(tài),并找到Network選項单山。
由于頁面通過滾輪滑動實現(xiàn)了加載數(shù)據(jù)碍现,所以筆者認為這是通過Ajax進行了數(shù)據(jù)渲染。
在Network下有一個XHR的選項米奸,這個選項便是頁面中出現(xiàn)的所有Ajax接口昼接。
對爬蟲工程師而言,最敏感的單詞之一莫過于page悴晰,即:頁碼慢睡。沒錯逐工,在Headers里的Request URL的鏈接便是我們需要的接口。
構(gòu)建請求頭
關(guān)于請求頭漂辐,我們需要構(gòu)建:
- User-Agent:防止被檢測為爬蟲程序
- X-Requested-With:Ajax請求頭
- Cookie:添加Cookie是為了爬取推送給本人賬號的數(shù)據(jù)
# 實例化UserAgent對象
user_agent = fake_useragent.UserAgent(use_cache_server=False)
url = 'http://www.reibang.com/?seen_snote_ids%5B%5D=66169577&seen_snote_ids%5B%5D=70078184&seen_snote_ids%5B%5D=59133070&seen_snote_ids%5B%5D=71131220&seen_snote_ids%5B%5D=69717831&seen_snote_ids%5B%5D=71082246&seen_snote_ids%5B%5D=69512409&seen_snote_ids%5B%5D=66364233&seen_snote_ids%5B%5D=68425069&seen_snote_ids%5B%5D=65829398&seen_snote_ids%5B%5D=70390517&seen_snote_ids%5B%5D=70715611&seen_snote_ids%5B%5D=60025426&seen_snote_ids%5B%5D=69454619&page={}'
# 請求頭
headers = {
# 隨機生成1個user-agent
'User-Agent': user_agent.random,
'X-Requested-With': 'XMLHttpRequest',
'Cookie': 'xxxxxxx',
}
# 設(shè)置代理(可省略)
proxies = {
'http': 'http://54.241.121.74:3128',
'https': 'http://54.241.121.74:3128'
}
需要注意泪喊,url鏈接的page屬性使用了{}進行后續(xù)頁碼的傳遞。
請求頁面
首先我們先構(gòu)建1個全局變量num用來對提取的數(shù)據(jù)進行計數(shù)者吁。
num = 1
接下來便是請求頁面了窘俺。
# 初始頁碼
count = 0
# 循環(huán)請求頁面
while True:
response = requests.get(
# 傳入頁碼
url=url.format(i),
headers=headers,
proxies=proxies
)
count += 1
# 解析頁面
title_and_link = get_data(response.text)
# 展示數(shù)據(jù)
show_data(title_and_link)
# 如果judge為True,代表已經(jīng)爬取了1000條數(shù)據(jù)
if num > 1000:
break
解析頁面
def get_data(text):
"""
提取頁面源碼中的信息
:param text: 頁面源代碼
:return: result
"""
# 生成正則對象
pattern = re.compile(r'<a class="title" target="_blank" href="(.*?)">(.*?)</a>', re.S)
# 查找符合上一行正則對象的數(shù)據(jù)
result = pattern.finditer(text)
return result
展示數(shù)據(jù)
def show_data(title_and_link):
"""
展示數(shù)據(jù)
:param title_and_link: 數(shù)據(jù)
:return: None
"""
# 重新聲明num
global num
for i in title_and_link:
# 打印數(shù)據(jù)
print(f'{num}:http://www.reibang.com{i.group(1).strip()}', end=' ')
print(i.group(2).strip())
num += 1
if num > 1000:
print('完成任務(wù)8吹省A隼帷!')
break
結(jié)語
這個爬蟲程序還是比較簡單的育八,畢竟找到接口对途,就可以一步步的深挖數(shù)據(jù)。
實際上髓棋,這個爬蟲程序存在著一些比較顯而易見的bug实檀,尤其是當你沒有設(shè)置Cookie的時候。
沒錯按声,由于接口原因膳犹,當我們沒有設(shè)置Cookie時,爬取的數(shù)據(jù)基本上是重復的签则,并且Cookie也并不能完美的解決這個問題须床。當數(shù)據(jù)量較大時,即使設(shè)置了Cookie也會出現(xiàn)重復的數(shù)據(jù)渐裂。
這個bug最直接的解決方案便是更換接口豺旬,但這樣做也代表著需要重構(gòu)部分代碼(雖然也沒多少代碼)。確實柒凉,通過Chrome的開發(fā)者工具查看族阅,其他的接口也是存在的,主要看你能不能找到罷了膝捞。此外坦刀,使用selenium也是一個不錯的選擇。此處也體現(xiàn)了爬蟲程序的主觀性蔬咬,即實現(xiàn)功能的方法是多種多樣的求泰。不過筆者想說的是,既然提到了去重计盒,那怎么能少了Redis呢渴频?
沒錯,下篇文章便是對上述的爬蟲程序進行去重的優(yōu)化操作北启。
關(guān)于本文的完整代碼卜朗,可以來筆者的GitHub下獲取拔第。
https://github.com/macxin123/spider/blob/master/jianshu/re_jianshu.py