圍觀微博網友發起的美胸比賽學習爬取微博評論內容


網友:看看胸
女:滾

網友:美胸比賽
女:[圖片消息] ​​​​

繼上次知乎話題 擁有一副好身材是怎樣的體驗? 解析了知乎回答內容之后,這次我們來解析一下微博內容,以微博網友發起的美胸大賽為例:

https://m.weibo.cn/detail/4367970740108457

https://m.weibo.cn/detail/4348022520956497

這就是本次要獲取的微博圖片內容,共計672張很凶的照片:

xiong.png

下面是講如何獲取的,不感興趣的話直接去公眾號回復 套圖 即可獲得。


首先進入開發者工具看一下微博結構:

weibocom.png
這只是一小部分,微博評論和微博用戶發的微博頁面,里面都是以html5格式傳到本地的,把內容格式化之后就會發現,層級非常復雜,有興趣的可以看一下,與其解析這個還不如用selenium更簡單一些。於是當時就產生了兩個思路:

  • 借助 splash 直接解析渲染后的頁面
  • 用 mitmproxy 抓手機APP微博的包,用 APPium 控制手機刷新評論

不管是哪一種,相對於只是獲取一下圖片而言都麻煩。於是去網上搜一下,搜索結果都是前兩年爬取微博的方法,那時候還是用 ajax 以 json 格式傳遞,現在明顯已經不是。

然后后面抱着僥幸心理把訪問形式改成手機,微博域名就從 weibo.com 變成了 weibo.cn,再看一下 network 選項卡以hotflow 開頭的 xhr :

weibocn.png

這時候 weibo.cn 傳給本地信息就是簡單的 json 格式啦。上圖就是微博評論列表的評論,可以看到每條評論如果有圖片,就會有 pic 屬性,但是要注意在 pic 下的 直接子 url 只是預覽圖鏈接,並非原圖。原圖鏈接在pic 屬性下 large 下的 url。其他的屬性是一些微博的標題、發送時間、內容、點贊數、評論數、轉發數和博主相關信息等。我們這次重點是圖片,就不管其他的了。

另外微博的反爬措施很強,真的惡心到我了,如果有大規模爬取需求,建議去淘寶買號,建 Cookie池,或者用代理池不停地切換訪問主機。如果只用自己電腦本地Cookie,那就把請求頭弄全,並限制抓取速度。

切換到 Headers 選項卡,看一下 Request URL

https://m.weibo.cn/comments/hotFlowChild?cid=4376866645060411&max_id=152030087630286&max_id_type=0

可以看出它的格式是

https://m.weibo.cn/comments/hotFlowChild? + cid + max_id + max_id_type'

其中 cid 是每一條微博的唯一ID,max_id 是下一次傳回數據的最后一條評論的 ID。也就是往下翻看評論,每次顯示十條,並在這次所看的評論里就傳回 下十條評論 的最后一條評論的唯一 ID,微博是根據這個 ID 傳回下十條內容。這也就直接限制了每次爬評論、微博、二級評論時只能一次獲取十條,也無法利用線程池加速,因為只有獲取了這十條才知道下十條請求地址里 max_id 的值。

然后就可以由這些信息構造請求,獲取 json 格式的響應結果:

comment_url = 'https://m.weibo.cn/comments/hotflow?id={weibo_id}&mid={weibo_id}&max_id={max_id}&max_id_type=0'
url = comment_url.format(weibo_id=id, max_id=0)
response = requests.get(url, headers=headers)
result = json.loads(response.text)

先獲取總評論數來計算需要多少次才能爬完評論:

total_number = result.get('data').get('total_number')
total_number = int(total_number)
for i in range(int(total_number / 10)):
    result = get_page(weibo_id)
    for url in parse_comment(result):
    	save_to_img(url)

下載完圖片只有700來張才知道靠后的評論都是無用的(男士跟答主要聯系方式什么的)評論。

然后就是獲取圖片地址:

def parse_comment(result):
    if result.get('ok') and result.get('data').get('data'):
        comments = result.get('data').get('data')
        for comment in comments:
            if comment.get('pic'):
                url = comment.get('pic').get('large').get('url')
                yield url

要先 if comment.get('pic') 一下,這很重要,因為很多無用評論並沒有配圖,也就是沒有 pic 屬性,要以這種方式過濾掉。

另外還有這個:

child_comment.png

這里的二級評論就很有必要爬一下,看一下結構:

child_com.png

值得注意的是二級評論里不管有沒有圖片都不會有 pic 屬性,圖片在回答內容text 里以 css 方式嵌套的,很明顯就是 a 標簽下的 href 屬性 就是圖片地址。用 pyquery 取出來地址:

childs_comment = result.get('data')
for child_comment in childs_comment:
	text = child_comment.get('text')
	content = pyquery.PyQuery(text)
	url = content('a').attr('href')
	yield url

存儲圖片以圖片內容的 md5 值命名,可以去重:

response = requests.get(url)
if response.status_code == 200:img_path = '{0}/{1}.{2}'.format(path,md5(response.content).hexdigest(), 'jpg')  # 以圖片的md5字符串命名防止重復圖片

最后接入某大廠的人體特征值檢測,考慮到圖片大多沒有露臉,識別男女性別不夠准,這里只把未識別出人體的圖片去掉了(一些表情圖)。

有興趣的可以公眾號回復 套圖 獲得這次微博圖片和上次知乎圖片

本次微博結構比較簡單,與上次關於知乎的文章差不多,不再提供源碼。

公眾號:愛寫bug(ID:iCodeBugs)

愛寫bug.png


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM