百度貼吧爬蟲:理解網頁的加載過程

最近在學習爬蟲,就順便記錄一下吧(つд⊂)
以百度貼吧的主題帖爲例子,首先,在百度貼吧主頁那個大大的搜索框旁邊,點那個小小的“高級搜索”,輸入關鍵詞,以“王思聰”爲例,enter後在排序結果那裏點主題帖(這種類型的帖子相關性比較高)

獲取該頁面的所有的入口鏈接。(最好要設置headers吧)

import requests

url = "http://tieba.baidu.com/f/search/res?isnew=1&kw=&qw=%CD%F5%CB%BC%B4%CF&rn=10&un=&only_thread=0&sm=1&sd=&ed=&pn=1"

header = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36'
}
cookie = {
    'cookie': 'xxxxxx'
}
s = requests.session()
try:
    html = s.get(url, headers=header, cookies=cookie)
    html.encoding = 'utf8'
    html = html.text
    print(html)
except Exception as e:
    print(e)

我們隨便點進一個帖子,按下F12和network,可以看到第一個鏈接:
original_url:
https://tieba.baidu.com/p/5843812080?pid=121504369111&cid=0&red_tag=1678531958
點擊Preview可以看到這個頁面包含的信息,注意注意!強烈建議通過Network去查看頁面信息而不是Elements,elements中顯示的是完全渲染好的頁面,但是現在大多數網頁的源碼都只有一個空架子,通過大量的js和jquery來填充其中信息,如果我們直接通過去get或者post這個url,往往會發現正則匹配不到我們所想要的信息。Preview是數據信息的可視化表現,源碼、未處理格式的原始數據在Response裏看。

如下圖所示,我發現一個問題,Preview中該鏈接頁面包含了各樓層的評論信息,但是不包含樓層的回覆信息。
這裏寫圖片描述

我找了很多個網頁發現都是這樣的,url對應的網頁源碼只包含了樓層的評論但沒有該樓層的回覆。。。咦惹,真的是神奇了(,,゚Д゚)

我開始不斷刷新頁面並查找Network處刷出來的鏈接,選擇XHR,最後看到一條名稱中包含totalComment的鏈接,點擊Preview並展開數據,很驚喜地看到content中有我們所想要的評論回覆數據,同時觀察發現,該頁面只有這一層樓的評論有回覆,回覆數據爲5條,因此,comment_list下121504396239
應該是該評論樓層的標識,comment_info下有多少條數據該樓層就有多少條回覆。
這裏寫圖片描述

同時發現該樓層所對應的源碼中id包含了這串奇怪的數據:

<div id="post_content_121504396239" class="d_post_content j_d_post_content ">            Cj表演賽,自己去看校長被主播虐成什麼樣吧</div><br>            

所以我們可以通過這串數字把回覆與樓層對應上去咯!(小聲逼逼:做網站的爲什麼要把樓層的評論和回覆分開呢……(●▼●;))

點開其他頁面觀察,驗證了我的想法。下面這個network可以看出該帖子有三層樓進行了對話,第一層樓有三個回覆。
這裏寫圖片描述

找到了重要的頁面和數據的對應方式,接下來我們看看這個totalComment的頭部參數:
totalComment_url: https://tieba.baidu.com/p/totalComment?t=1534488858327&tid=5843812080&fid=1593767&pn=1&see_lz=0

t: 1534488858327
tid: 5843812080
fid: 1593767
pn: 1
see_lz: 0

tid在原帖入口url可以匹配到:tid = re.findall(r'p/(.*?)?pid', url)[0]
pn是頁碼,see_lz爲1表示只看樓主。令人頭疼的來了……什麼是t和fid呢…………

我把t和fid數據串粘貼到original_url的Response中查找,結果t所應對的數據串匹配不到,但是fid多處都匹配到了,所以可以很容易寫一個正則:

f_id_match = re.findall(r'"forum_id":(.*?),"level_1_dir_name"', html, re.S)

花了一段較長的時間去找這個t到底是什麼東西……一度懷疑自己這個思路是不是錯的……

後來我發現多次訪問該鏈接,對應的t數據會不一樣,那麼,大概就是時間戳了!!測試了一下發現果然如此耶,所以:

t = int(round(time.time() * 1000))  # 當前時間戳,13位

ok,那麼對回覆數據的請求就如下啦:

    comment_url = r'https://tieba.baidu.com/p/totalComment?'
    # 請求回覆的數據
    comment_html = s.get(comment_url, params={'t': t, 'tid': tid, 'fid': fid, 'pn': '1', 'see_lz': '0'})
    comment_html.encoding = 'utf8'
    comment_json = comment_html.json()

我將返回來的數據處理成了json格式,提取post_id和content處理成字典,可以通過post_id的對應,該回復對應回樓層。

爬了一個多星期的蟲,感覺爬蟲比較重要的就是理解網頁的請求過程,要學會在Network中查找有用的數據頁,探索一下各個參數(對了,上面百度貼吧的例子中還沒有實現分頁)

後面會繼續寫學習過程中接觸到的一些工具。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章