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

網友:看看胸
女:滾

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

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

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

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

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

xiong.png

下面是講如何獲取的,不感興趣的話直接去公衆號回覆 套圖 便可得到。json


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

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

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

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

而後後面抱着僥倖心理把訪問形式改爲手機,微博域名就從 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

相關文章
相關標籤/搜索