python3爬取新浪微博所有評論數據
該項目主要根據具體某篇微博的網址,得到其下所有評論的信息,包括評論用戶名,評論人的主頁網址,評論時間,內容;然後存儲在csv中(僅供學習)
原理:微博的評論數據是通過服務器異步傳輸過來的,並且是分多頁的,相信很多小夥伴有了分頁的網址,就能把評論數據解析出來,但是微博的評論數據是通過瀑布流分頁,獲取下一頁的url也就是此次爬取的難點。
通過評論頁的url,以及掉我頭髮的分析之後,
首頁評論url:https://weibo.com/aj/v6/comment/big?ajwvr=6&id=4441135474874422&filter=all&from=singleWeiBo&__rnd=1574405759566
第二頁評論url:https://weibo.com/aj/v6/comment/big?ajwvr=6&id=4441135474874422&root_comment_max_id=4441415025138397&root_comment_max_id_type=&root_comment_ext_param=&page=2&filter=all&sum_comment_number=11&filter_tips_before=1&from=singleWeiBo&__rnd=1574405986800
可以看出第二頁url比第一頁多了幾個參數,其中root_comment_max_id與sum_comment_number決定這能否獲取下一頁評論數據
root_comment_max_id是上一頁最後一條評論的comment_id-1
sum_comment_number是已經展示的評論數。
(簡單吧,拿頭髮換的)
這樣我們就能通過首頁url構造出下一頁的url,如此循環得到所有評論頁的url
以下是其評論數據:
爬取流程如下:
首先,從文件中讀取要爬取的微博的網址
if __name__ == '__main__':
# 創建一個保持會話的session
s = requests.Session()
with open('wb_url.txt','r') as f:
for url in f:
# print(url)
spider = Spider(url,s)
spider.run()
有了具體某篇微博的網址後,可以得到該微博評論的id,然後拼出評論首頁的url
# 得到第一頁評論網址,和該博客評論id
def get_first_comment(self):
res = self.get_response(self.page_url)
# 得到該微博的id
com_id = re.search(r'按熱度.*?id=(.*?)&filter=all.*?">按時間', res.text).group(1)
# 然後拼出其首頁評論的網址
com_url = 'https://weibo.com/aj/v6/comment/big?ajwvr=6&id=%s&filter=all&from=singleWeiBo&__rnd=1574358480600' % com_id
return com_url, com_id
有了評論首頁地址,我們就可以通過其源碼提取到我們需要的root_comment_max_id並計算出sum_comment_number。這樣我們就可以拼出下一評論頁的url
#通過評論源碼得到下一頁的url
def get_next_comment(self,com_data,com_id):
# 得到最後一個評論的comment_id
# print(com_data)
html = etree.HTML(com_data)
com_ls = html.xpath('//div[@node-type="root_comment"]')
# 評論爲空時的容錯
try:
com_max_id = com_ls[-1].xpath('./@comment_id')[0]
except:
return 'NO'
com_max_id = str(int(com_max_id)-1)
length = len(com_ls)
self.sum_comment_number += length
# print(com_max_id, length)
next_url = 'https://weibo.com/aj/v6/comment/big?ajwvr=6&id={cid}&root_comment_max_id={mid}&root_comment_max_id_type=&root_comment_ext_param=' \
'&page={page_num}&filter=all&sum_comment_number={count_num}&filter_tips_before=1&from=singleWeiBo&__rnd=1574357153056'.format(cid=com_id,mid=com_max_id,page_num=self.page_num,count_num=self.sum_comment_number)
return next_url
有了評論頁的url,我們只需解析一下服務器返回的評論數據,得到我們需要的數據,並保存
def save_comment_data(self,com_data):
# 提取乾淨評論 用戶名+內容+時間+主頁url
html = etree.HTML(com_data)
# 得到該評論源碼的所有評論
uls = html.xpath('//div[@class="list_con"]')
for ul in uls:
user = ul.xpath('./div[@class="WB_text"]/a/text()')[0]
comment = ul.xpath('./div[@class="WB_text"]/text()')[1]
# 去除中文冒號:
comment = comment.split(':',maxsplit=1)[-1]
tim = ul.xpath('./div[contains(@class,"WB_func")]/div[contains(@class,"WB_from")]/text()')[0]
user_url = 'https:'+ul.xpath('./div[@class="WB_text"]/a/@href')[0]
try:
self.writer.writerow([user, comment, tim,user_url])
except Exception as e:
print(e)
# print(user, comment, tim,user_url)
主要流程就是如此,此次最花時間的就是下一頁評論url的獲取,新浪微博採用瀑布流,鼠標下滑或點擊查看更多服務器纔會返回數據,通過上一頁的數據,推算出下一頁url的參數~
以前新浪微博,通過page參數就能得到下一頁,現在升級,後浪在推前浪,而我還想再浪,加油