文章首發自個人公衆號【poython3xxx】。未經受權,禁止轉載。html
做爲一名十好青年,微博也關注了許多互聯網&科技類的博主。本着學習的心態平常刷着微博。忽然看到一條微博。node
點開評論,瞬間驚呆了。python
下圖可能引發不適,未成年人,請在家長的陪同下觀看。git
評論1.5W條,一頁一頁的去翻,身爲程序員這顯然不是咱們的風格。本着學習爲主的心態,我決定把他們都保存在個人硬盤裏!!!程序員
俗話說,能爬移動端就不要爬PC端,可是在操做手機抓包爬的過程當中,遇到了不少坑。一時沒有解決。因而轉移陣地到PC端微博。github
F12打開開發者工具,刷新頁面。看到有這樣一條Get請求 weibo.com/aj/v6/comment/big,當咱們點擊加載更多時,又會從新發送一次這樣的請求。json
請求參數以下: 微信
響應爲一個json串,微博的內容以html的形式返回。 cookie
通過對比發現,請求參數 ajwvr爲定值6;id爲該微博動態的ID,也能夠理解爲定值;from的值也爲定值,_rnd 參數無關緊要並不會影響最終的結果。ide
一開始 root_comment_max_id這個參數讓我比較疑惑,第一次請求中並無這個參數,後面的請求中都必需要傳這個參數,不然會影響最後的響應結果。 根據字面意思,大概是父級內容的id,因而我把上一次請求的html數據複製到VSCode,直接Ctrl+F 全局搜索root_comment_max_id。果真不出所料。
至此,每一個參數的含義,基本都清楚了。必傳參數總結以下:
ajwvr :定值6,必傳。
id : 該條微博動態的id。
from : 定值 singleWeiBo
root_comment_max_id:在上一個請求響應的html中提供。也有提供分頁的做用
分析相應的html,經過xpath提取出咱們想要的字段。
也許你們只對最終的結果感興趣,那我就不具體講了。只展現一下關鍵的代碼。
微博爬蟲中,作了必定的反爬措施。
同一IP不能訪問頻繁。
請求頭中須要攜帶Cookie
headers = {
'Cookie': '你的cookie',
}
# 參數信息
params = {
'ajwvr': 6,
'id': '4367970740108457',
'from': 'singleWeiBo',
'root_comment_max_id':''
}
# 訪問url
URL = 'https://weibo.com/aj/v6/comment/big'
resp = requests.get(URL, params=params, headers=headers)
resp = json.loads(resp.text)
if resp['code'] == '100000':
html = resp['data']['html']
print(html)
from lxml import etree
html = etree.HTML(html)
# 獲取該頁面的root_comment_max_id ,爲下一次請求提供參數
max_id_json = html.xpath('//div[@node-type="comment_loading"]/@action-data')[0]
node_params = parse_qs(max_id_json)
# max_id
max_id = node_params['root_comment_max_id'][0]
params['root_comment_max_id'] = max_id
# data = html.xpath('//div[@class="list_ul"]/div[@node-type="root_comment"]/div[@class="list_con"]')
# 獲取每一條動態的節點信息
data = html.xpath('//div[@node-type="root_comment"]')
# 遍歷每一條東岱
for i in data:
# 評論人暱稱
nick_name = i.xpath('.//div[@class="WB_text"]/a/text()')[0]
# 評論內容。
wb_text = i.xpath('.//div[@class="WB_text"][1]/text()')
# 簡單的清洗,出去空格和換行符
string = ''.join(wb_text).strip().replace('\n', '')
# 封裝了一個方法,將留言信息寫入文本
write_comment(string)
# 評論id , 用於獲取評論內容
comment_id = i.xpath('./@comment_id')[0]
# 評論的圖片地址
pic_url = i.xpath('.//li[@class="WB_pic S_bg2 bigcursor"]/img/@src')
pic_url = 'https:' + pic_url[0] if pic_url else ''
# 封裝的下載圖片方法
download_pic(pic_url, nick_name)
複製代碼
以上是獲取評論信息,可是每條評論下還有不少別的小姐姐的評論(胸照),這咱們確定不能放過。
點擊相似放上的按鈕,發現依舊有個請求,地址與上面提到的地址同樣。區別在於參數的不一樣。具體你們能夠實際操做一下。
經過分析子評論的圖的獲取方式有所不一樣,他是經過get請求 weibo.com/aj/photo/popview, 參數可有從子評論響應的html獲取。下圖標註部分。
經過請求構造出的url,會返回一個一個圖片列表,第一個就是咱們須要的圖。
獲取子評論方法,代碼中只獲取了第一頁的子評論,由於後面大部分是水文,感興趣的同窗能夠去試試,方法跟獲取父級留言同樣,須要的參數在源碼中均可以找到。
def get_child_comment(root_comment_id):
comment_params['root_comment_id'] = root_comment_id
resp = requests.get(URL, params=comment_params, headers=headers)
resp = json.loads(resp.text)
if resp['code'] == '100000':
html = resp['data']['html']
print(html)
from lxml import etree
html = etree.HTML(html)
# 每一個子評論的節點
data = html.xpath('//div[@class="WB_text"]')
for i in data:
nick_name = ''.join(i.xpath('./a/text()')).strip().replace('\n', '')
comment = ''.join(i.xpath('./text()')).strip().replace('\n', '')
write_comment(comment)
# 獲取圖片對應的html節點
pic = i.xpath('.//a[@action-type="widget_photoview"]/@action-data')
pic = pic[0] if pic else ''
if pic:
# 拼接另外兩個必要參數
pic = pic + 'ajwvr=6&uid=5648894345'
# 構造出一個完整的圖片url
url = 'https://weibo.com/aj/photo/popview?' + pic
resp = requests.get(url, headers=headers)
resp = resp.json()
if resp.get('code') == '100000':
# 從忽然url中,第一個就是評論中的圖
url = resp['data']['pic_list'][0]['clear_picSrc']
# 下載圖片
download_pic(pic_url, nick_name)
複製代碼
好了,知道你們已經火燒眉毛的想看結果了。部分截圖以下。
也能夠經過PIL模塊生成照片牆。
微博裏,你們都在說什麼?能夠經過詞雲的方式進行展現
今天下班已經十點了,路上刷微博,忽然想嘗試爬一下微博評論,時間倉促,代碼可能不夠嚴謹。因此各位看官多擔待,完整源碼。已上傳github。 地址:github.com/python3xxx/…
最後歡迎你們關注個人公衆號,微信搜索【python3xxx】。天天都會有不同的Python乾貨。