前言:
使用多進程爬蟲方法爬取簡書網熱評文章,並將爬取的數據存儲於MongoDB數據庫中
本文爲整理代碼,梳理思路,驗證代碼有效性——2020.1.17
環境:
Python3(Anaconda3)
PyCharm
Chrome瀏覽器
主要模塊: 後跟括號內的爲在cmd窗口安裝的指令
requests(pip install requests)
lxml(pip install lxml)
re
pymongo(pip install pymongo )
multiprocessing
proxiesIp(自定義的IP代理池庫,可以不要)
1
爬取簡述網熱門文章信息(用戶ID、標題、文章內容、評論數、點贊數、打賞數)
2
2.1.通過觀察可以發現該網頁沒有具體的分頁,一直滑動頁面可以一直瀏覽,由此可以判斷該頁面爲異步加載(即不刷新整個網頁,只進行局部的更新加載)。
2.2.打開開發者工具 F12 按Network選項,並滾動頁面,我們發現請求返回了一些數據,而這些數據里正有我們需要訪問的真實URL,由此我可以構造相應的url列表解析式。
3
我們需要以下文章信息:用戶ID、標題、文章內容、評論數、點贊數、打賞數,使用XPath我們對該網頁進行解析。
# 用戶ID
author = info.xpath('div/div/a[1]/text()')[0]
# 文章標題
title = info.xpath('div/a/text()')[0]
# 文章內容
content = info.xpath('div/p/text()')[0].strip()
# 評論數
comment = info.xpath('div/div/a[2]/text()')[1].strip()
# 點贊數
like = info.xpath('div/div/span[2]/text()')[0].strip()
# 打賞數
rewards = info.xpath('div/div/span[3]/text()')
if len(rewards) == 0:
reward = '無'
else:
reward = rewards[0].strip()
因爲並非所有文章都有打賞,所以,我們對其進行判斷
4
使用多進程,首先導入使用多進程所需的庫
from multiprocessing import Pool
其次,創建進程池,這裏的processes是指同步發生的進程數量
測試發現,在爬取簡書網熱評文章時,processes越大,返回的HTTP狀態爲429(請求次數過多)的情況越多,這裏爲2時最佳。
pool = Pool(processes=2)
最後,調用進程爬蟲
調用進程爬蟲,這裏使用的是一個map函數,第一個參數是一個函數,第二個參數是一個列表,這裏的意思是將列表中的每個元素作用到前面這個函數中。
pool.map(get_jianshu_info, urls)
5
將數據插入到MongoDB數據庫中
5.1.首先,導入必要的pymongo庫
import pymongo
5.2.其次,連接並創建數據庫即數據集合
# 連接數據庫
client = pymongo.MongoClient('localhost', 27017)
# 創建數據庫和數據集合
mydb = client['mydb']
jianshu_shouye = mydb['jianshu_shouye']
5.3.最後插入數據到數據庫’jianshu_shouye‘中
data = { 'author':author,
'title':title,
'content':content,
'comment':comment,
'like':like,
'reward':reward
}
# 插入數據庫
jianshu_shouye.insert_one(data)
完整代碼
說明:該代碼僅爲了學習一下爬蟲技術,在url構造時只爬取兩頁,可自行修改。另,代理IP池(from proxiesIP_1_1 import proxiesIp)可以不要,測試時爲了防止被封IP加入的。還有有什麼問題可以在評論裏說明一下。
# 導入庫
import requests
from lxml import etree
import pymongo
from multiprocessing import Pool
from proxiesIP_1_1 import proxiesIp
# 連接數據庫
client = pymongo.MongoClient('localhost', 27017)
# 創建數據庫和數據集合
mydb = client['mydb']
jianshu_shouye = mydb['jianshu_shouye']
headers = {'user-agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) '
'AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.88 Safari/537.36'}
# 定義獲取信息的函數
def get_jianshu_info(url):
ip = proxiesIp.selectIp()
html = requests.get(url=url, headers=headers, proxies=ip)
print(url, html.status_code)
selector = etree.HTML(html.text)
# 獲取大標籤,以此循環
infos = selector.xpath('//ul[@class="note-list"]/li')
for info in infos:
try:
# 用戶ID
author = info.xpath('div/div/a[1]/text()')[0]
# 文章標題
title = info.xpath('div/a/text()')[0]
# 文章內容
content = info.xpath('div/p/text()')[0].strip()
# 評論數
comment = info.xpath('div/div/a[2]/text()')[1].strip()
# 點贊數
like = info.xpath('div/div/span[2]/text()')[0].strip()
# 打賞數
rewards = info.xpath('div/div/span[3]/text()')
if len(rewards) == 0:
reward = '無'
else:
reward = rewards[0].strip()
data = { 'author':author,
'title':title,
'content':content,
'comment':comment,
'like':like,
'reward':reward
}
print(data)
# 插入數據庫
jianshu_shouye.insert_one(data)
except IndexError:
# pass掉IndexError錯誤
pass
# 程序主入口
if __name__ == '__main__':
urls = ['https://www.jianshu.com/c/bDHhpK?order_by=top&page={}'.format(str(i)) for i in range(1, 3)]
# 創建進程池
pool = Pool(processes=2)
# 調用進程爬蟲
pool.map(get_jianshu_info, urls)