(聲明:該文章只作學習探討,爬取內容不用作任何商業目的。)
經?;煳⒉┑耐瑢W應該知道“榜姐”(微博搞笑排行榜),她經常會在深夜發一些話題讓粉絲自由發揮,一般來說這些微博的質量都比較高,這篇的需求就是爬取這些話題微博以及熱門評論。
涉及知識:
1、request的基本使用
2、json解析
3、正則匹配
4、xpath的string函數過濾多余標簽
本篇目錄:
- 繞過登錄訪問博主的主頁
- 尋找獲取微博內容的api
- 尋找獲取某條微博的所有評論的api
- 思路
- 完整代碼
- 輸出示例:(按Markdown格式的輸出)
- 參閱
繞過登錄訪問博主的主頁
一般pc站信息比較全,但同時也不太容易爬取,因為一些登錄驗證的問題或者其他原因。所以一般寫爬蟲,pc站比較困難的時候,我們可以選擇m站或者wap站。
這篇我們就爬取微博的m站,也就是移動端的站點m.weibo.cn。我們選擇它的一個重要原因就是,可以不用登錄。例如,要訪問某博主(這里以“榜姐”為例)的微博主頁,只需要訪問:
m.weibo.cn/u/1713926427
u是user的意思,后面的數字就是她的用戶id。我們可以通過在pc端自己手動登錄,搜索某個博主,訪問其主頁時,按F12打開Network抓包找到id號碼。如圖:
這是通用的方法,因為“榜姐”有個性域名,所以需要這樣找,其他沒有個性域名的用戶,通過搜索找到以后,其實不難發現搜索結果上的博客地址里就有用戶id。
尋找獲取微博內容的api
找到用戶id后,我們用來訪問m站,在Network搜索api發現有兩個已經發送的api請求。
此時在“主頁”頁面,我們點擊“微博”,會發現又發送了一個api請求,這就是我們要找的獲取所有微博的api。就是下圖中containerid是107開頭的這條,我們點擊查看一下詳細信息。
在右邊選擇preview預覽一下json,可以發現在cards中任選一個card,其中的mblog標簽下果然有我們要的博文數據。說明這就是我們要找的api。
(注:在cardlistInfo標簽下,可以發現這個第一頁對應的page值是2,說明page是從2開始的,之后會用到page參數來翻頁。同時注意一下這個scheme里的url,之后會講到。)
接下來我們來分析一下這個api的參數,很明顯這是一個用get方式發送的請求,從headers里也可以看到請求方式是GET。所以只需要分析?后面這些參數就可以了。
https://m.weibo.cn/api/container/getIndex?type=uid&value=1713926427&containerid=1076031713926427
顯然type=uid肯定是不變的,value=1713926427就是用戶的id值,經過對比也可以發現后面的containerid其實只是107603后跟著用戶id。多驗證幾個用戶會發現確實如此。
尋找獲取某條微博的所有評論的api
看到之前提到的scheme,將它的url復制粘貼到地址欄訪問,可以發現是進入到了這條微博,在Network搜索api發現我們需要的獲取評論的api。
分析一下第二個api的參數(在控制臺里對api右鍵可以copy這條url)
https://m.weibo.cn/api/comments/show?id=4112893156959108&page=1
顯而易見,id就是該條微博的id,page是評論的翻頁參數。
思路
獲得了兩個api,我們接下來就要寫代碼進行爬取了。思路很清晰:
1、獲取目標博主id。
2、根據博主id,用第一個api獲取指定頁的微博的json返回(包括內容和對應id)。
3、根據微博id,用第二個api獲取評論的json返回。
4、解析json即可。這里推薦一個比較好用的在線解析json的網站: json.cn 。當然,你也可以在控制臺的Network里用Preview對json進行預覽。
完整代碼
細節見注釋~
# -*- coding:utf-8 -*-
'''
Created on 2017年5月30日
@author: wycheng
'''
from lxml import html
import requests
import json
import re
class CrawlWeibo:
# 獲取指定博主的所有微博card的list
def getWeibo(self,id,page):#id(字符串類型):博主的用戶id,page(整型):微博翻頁參數
url='https://m.weibo.cn/api/container/getIndex?type=uid&value='+id+'&containerid=107603'+id+'&page='+str(page)
response=requests.get(url)
ob_json=json.loads(response.text)
list_cards=ob_json['cards']
return list_cards# 返回本頁所有的cards
# 返回某條微博的熱門評論的list
def getComments(self,id,page):# id(字符串類型):某條微博的id,page(整型):評論翻頁參數
url='https://m.weibo.cn/api/comments/show?id='+id+'&page='+str(page)
response=requests.get(url)
ob_json=json.loads(response.text)
list_comments=ob_json['hot_data']
return list_comments
def printAllTopic(self,page):
list_cards=self.getWeibo('1713926427',page)
# 遍歷當頁所有微博,輸出內容,并根據id查找輸出熱門評論
for card in list_cards:
if card['card_type']==9:# 過濾出微博,card_type=9的是微博card,card_type=11的是推薦有趣的人
id=card['mblog']['id']
text=card['mblog']['text']
if re.search('___', text)!=None:# 用正則匹配,將博文有下劃線的微博過濾出來,有下劃線的是“話題微博”
print '***'
print u"### 話題: "+text+'\n'
#根據微博id獲取熱門評論,并輸出
list_comments=crawl_weibo.getComments(id, 1)# 熱門評論只需要訪問第一頁
count_hotcomments=1
for comment in list_comments:
created_at=comment['created_at']# 發表日期時間
like_counts=comment['like_counts']# 點贊數
text=comment['text']# 評論內容
tree=html.fromstring(text)
text=tree.xpath('string(.)')# 用string函數過濾掉多余標簽
name_user=comment['user']['screen_name']# 評論者的用戶名
source=comment['source']# 來源于哪個終端
if source=='':
source=u'未知'
pic_url=''# 評論內容的圖片
if 'pic' in comment:
pic_url=comment['pic']['url']
# 輸出評論數據
print str(count_hotcomments),': **',name_user,'**',u' **發表于:**'+created_at,u' **點贊:**'+str(like_counts)+u' **來自:**'+source
print text+'\n'
count_hotcomments=count_hotcomments+1
print '***'
#實例化爬蟲類并調用成員方法進行輸出
crawl_weibo=CrawlWeibo()
crawl_weibo.printAllTopic(2)# 只輸出一頁進行示例展示
輸出示例:(按Markdown格式的輸出)
話題: 你是在什么時候決定放棄一個人的 _____________________________ ???
1 : ** 沢與樹 ** 發表于:05-29 00:00 點贊:65690 來自:iPhone 6s
“當我點開這條微博的時候,我就知道我還沒放棄”
2 : ** 華水第一帥 ** 發表于:05-29 00:41 點贊:35305 來自:紅米Note 3
帶上你的備注,滾回你的大眾分組。
3 : ** 關鍵我叫梅仁耀丶 ** 發表于:05-29 00:00 點贊:49771 來自:未知
她戀愛了。
4 : ** 圈兒大王 ** 發表于:05-29 00:00 點贊:46084 來自:未知
發現自己愛他卑微到沒有了自尊,終于攢夠了失望,狠心決定還是離開吧。一瞬間心如刀絞,一瞬間如釋重負。有關于你,絕口不提,但如果有下次,可不可以換你,愛我到瘋掉
5 : ** 飯真的好好吃啊 ** 發表于:05-29 00:08 點贊:37621 來自:貓吃了那個iPhone
“你哭夠了沒有,哭夠了我掛電話了。”
6 : ** 你猜我是不是你媽啊 ** 發表于:05-29 00:03 點贊:35029 來自:vivo X5·K歌之王
3分鐘兩萬評論 被愛的那兩萬人真幸福
7 : ** 納達斯克 ** 發表于:05-29 00:00 點贊:30216 來自:未知
真心喜歡的人好像從來都放棄不了
8 : ** qqyyhh丶 ** 發表于:05-29 00:02 點贊:25563 來自:iPhone 6
每次失望一次,我就少做一件愛你的事,直到最后備注改成全名。取消特別關注,上線不主動找你,收起你送的東西,刪掉你所有的照片,再也不偷偷看你的時候,就是該說再見的時候了。