一行代碼爬取微博熱搜

一、前言

今天的分享來滿足讀者的需求,想讀 “關於數據庫 sql 或者 MySQL 的,就那種 Python 來處理數據庫,比如 Python 爬蟲爬到數據,然後封存到數據庫裏面,然後再從 sql 裏面讀取,進行分析可視化”。

後面寫文章一方面是自己學習筆記,另外也會針對讀者需求寫一些專題文章,如果你有自己的想法,歡迎瀏覽器訪問下方鏈接,給博主提意見:

https://shimo.im/forms/pVQRXG6gWyqPxCTY/fill?channel=wechat

二、專欄概要

三、直接來:爬取微博熱搜數據

3.1 找到數據源,頁面分析

首先我們直接瀏覽器搜索微博熱搜,就可以很快的找到微博熱搜的在線頁面,地址如下:

https://s.weibo.com/top/summary/

我們要爬取的熱搜榜數據,包括瞭如下列表中的四個字段。

話不多說,看到數據在頁面,按住 F12 調出瀏覽器開發者工具(推薦使用谷歌瀏覽器),然後點擊 network,刷新頁面,在加載出來的頁面中找到summary,發現這個請求返回來的是頁面中的數據,裏面是 html 代碼(數據也在裏面)。然後點擊Headers,可以看出請求的 url 就是我們瀏覽器裏輸入的鏈接,沒有其他接口,所以,接下來就簡單了。

3.2 一行代碼爬取微博熱搜

接下來說下簡單的數據獲取方式,只需一行代碼即可,如果硬是要算,最多就是兩行。

import pandas as pd
pd.read_html('https://s.weibo.com/top/summary/summary'index_col=0)[0]

(做這個項目的時候我是先用的後一種方式爬取的數據) 中間分析 xpath 路徑的時候突然發現,直接使用 pandas 的 read_html 函數即可,於是就有了上面一行代碼爬取到微博熱搜的想法了。

當然,我們會發現爬取的數據還是有點問題,雖然已經是DataFrame數據格式了,但是熱搜標題和熱搜熱度由於在一個 td 裏,所以爬取的時候也是給放到了一列中,着實有點尷尬。

不過沒關係,我們處理下,可以利用正則將標題和熱度分成兩列即可。

首先對數據進行簡單處理,設置下列名和刪除推薦熱搜(熱搜排名爲'•')和置頂熱搜(熱搜排名爲 nan)。

# 重新設置表頭
wb_hot_data.columns = ['wb_rank''wb_title_hot''wb_lable']
# 簡單處理數據,去除推薦熱搜和置頂熱搜
wb_hot_data = wb_hot_data.drop(wb_hot_data[(wb_hot_data['wb_rank']=='•') | pd.isna(wb_hot_data['wb_rank'])].index)

使用正則表達式提取數據,將熱搜標題和熱搜熱度分成兩列

import re
def reg_str(wb_title_hot='迪麗熱巴玩泡泡機 293536'):
    data = re.match('(.*?) (\d+)', wb_title_hot)
    if data:
        return data[1],data[2]
    else:
        return None,None
# apply函數應用
wb_title_hots = wb_hot_data.apply(lambda x: reg_str(x['wb_title_hot']),axis=1)
# 列表推倒式將熱搜標題和熱搜熱度值分別賦值給兩個新列
wb_hot_data['wb_title'] = [wb_title_hots[i][0] for i in wb_title_hots.index]
wb_hot_data['wb_hot'] = [int(wb_title_hots[i][1]) for i in wb_title_hots.index]

這樣數據基本就解決好啦~整體來看,還是會比後一種方法更簡單,如果你是爬蟲初學者,我建議你可以仔細看下接下來的一種數據爬取、解析方法。

3.3 爬蟲初學者看這裏,爬蟲入門模板教程如何爬去微博熱搜

直接無腦套入爬蟲模板:

# 爬蟲基礎庫,需要提前pip install requests 安裝
import requests
# html文本解析庫,將文本內容解析成html,方便使用xpath方式提取數據
from lxml import etree


def get_respones_data(wb_url = 'https://s.weibo.com/top/summary/'):
    '''
    參數:wb_url 字符串 要請求的url,默認:https://s.weibo.com/top/summary/
    返回:get_data,a 元組 第一個元素爲請求得到的頁面文本數據(可以後期使用正則表達式提取數據) 第二個元素爲將get_data文本內容解析成html後的內容,方便使用xpath方式提取數據
    '''
    headers={
        'Host''s.weibo.com',
        'User-Agent' : 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.131 Safari/537.36'
    }
    # requests 發送請求
    get_response = requests.get(wb_url,headers=headers)
    # 將返回的響應碼轉換成文本(整個網頁)
    get_data = get_response.text
    # 解析頁面
    a = etree.HTML(get_data)
    return get_data,a
# 調用函數,獲取到數據  
get_data,first_a = get_respones_data()

覺得這種方法比較麻煩的,可以跳過本部分,後面會介紹一種特別簡單的數據獲取方式(後面纔想到的,之所以先記錄這種麻煩方法,也是想讓大家學習下這種方法,後面數據爬取中會比較常見)。

接下來,我們就開始從爬取到的數據中提取我們需要的數據啦!

3.3.1 熱搜標題

首先在熱搜頁面,按住 F12,調出開發者工具,點擊開發者工具左上角的select an element...,然後選中自己想提取的數據,如下圖中的熱搜標題選中並點擊下熱搜標題,這是時候會迴歸正常模式(非選擇元素模式),如下圖,鼠標移動到被選中的 html 代碼上,然後右鍵,選擇 Copy-> Copy Xpath,就可以輕鬆的獲取到標題對應的 xpath 路徑啦。例如:

//*[@id="pl_top_realtimehot"]/table/tbody/tr[2]/td[2]/a

獲取到數據對應的 xpath 路徑後,我們就可以調用 lxml 中的 xpath 函數進行數據提取啦,如下代碼,輸出結果爲一個列表,列表裏的元素就是我們的熱搜標題。

這裏需要注意的是,我們是獲取 a 標籤內的文本內容,所以需要在獲取的 xpath 路徑後在加上\text(),同樣的,如果有需要我們還可以獲取標籤內的元素對應的值,如熱搜對應的鏈接。

# 熱搜標題
print(first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr[2]/td[2]/a/text()'))

'''
輸出:['小米放棄MI品牌']
'''

獲取到一條數據後,我們就要開始想獲取頁面所有標題數據啦,方法也很簡單,我們按照上面的方法,在隨便獲取一個熱搜標題的 xpath 路徑,然後對比一下,取相同就可以了。

如下代碼所示,我們發現兩個 xpath 路徑只有tr這一級不同,所以將 tr 後的 [2] 去掉即可。

'''
對比找出通用xpath路徑
//*[@id="pl_top_realtimehot"]/table/tbody/tr[2]/td[2]/a
//*[@id="pl_top_realtimehot"]/table/tbody/tr[4]/td[2]/a
'''
# 通用
wb_titles = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr/td[2]/a/text()')
print(len(wb_titles))
print(wb_titles)

看輸出數據,我們會發現數據總數對不上,頁面上的熱搜明明只有 50 條,爲什麼我們跑出來的數據有 53 條?有隱藏數據被我們爬出來了?當然不是,出現這種情況是因爲微博有一個置頂熱搜(暫且這麼稱呼),另外還會有 1-3 個微博推薦熱搜(暫且這麼稱呼),這兩種數據只有標題屬性,沒有其他如:排行、熱度、標籤等屬性,分析的時候需要剔除。

按上面的方法,我們可以依次獲取到熱搜熱度、熱搜排名、熱度標籤。

3.3.2 熱搜熱度

# 熱搜熱度
print(first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr[2]/td[2]/span/text()'))

# 輸出:['2866232']

'''
對比找出通用xpath路徑
//*[@id="pl_top_realtimehot"]/table/tbody/tr[2]/td[2]/span
//*[@id="pl_top_realtimehot"]/table/tbody/tr[4]/td[2]/span
'''
# 通用
wb_hot = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr/td[2]/span/text()')
print(len(wb_hot))
print(wb_hot)

3.3.3 熱搜排名

# 熱搜排名
'''
對比找出通用xpath路徑
//*[@id="pl_top_realtimehot"]/table/tbody/tr[10]/td[1]
//*[@id="pl_top_realtimehot"]/table/tbody/tr[7]/td[1]
'''
# 通用
wb_rank = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr/td[1]/text()')
print(len(wb_rank))
print(wb_rank)

3.3.4 熱度標籤

# 熱度標籤
'''
對比找出通用xpath路徑
//*[@id="pl_top_realtimehot"]/table/tbody/tr[4]/td[3]/i
//*[@id="pl_top_realtimehot"]/table/tbody/tr[7]/td[3]/i
'''
# 通用
wb_lable = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr/td[3]/i/text()')
print(len(wb_lable))
print(wb_lable)

這樣每個部分的數據都獲取到了,但是我們需要將每個熱搜的數據連接起來,現在由於裏面會有置頂熱搜和微博推薦熱搜,所以有些數據沒法直接連接起來,比如熱搜標題和熱度標籤。

當然,辦法肯定是有的,前面分析、複製 xpath 的時候,我們已經發現每個 xpath 只有 tr[n] 中的 n 不同,所以寫個循環變動 n 即可,這樣每次獲取每條熱搜對應的相關數據即可。

新問題來了,n 是多少呢?顯然 n 不會是個定值(微博推薦熱搜條數不定),我們再仔細觀察頁面,可以發現不管是微博熱搜、置頂熱搜還是推薦熱搜,標題都是有的,所以我們看標題數即可。如下代碼。

# 通用
wb_titles = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr/td[2]/a/text()')
n = len(wb_titles)
wb_hot_data = []

# 提取數據
def get_element(data_list):
    if data_list:
        return data_list[0]
    else:
        return None
    
# 遍歷循環
for i in range(n):
    wb_rank = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr[%d]/td[1]/text()'%(i+1))
    wb_titles = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr[%d]/td[2]/a/text()'%(i+1))
    wb_hot = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr[%d]/td[2]/span/text()'%(i+1))
    wb_lable = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr[%d]/td[3]/i/text()'%(i+1))
    wb_hot_data.append([get_element(wb_rank), get_element(wb_titles), get_element(wb_hot), get_element(wb_lable)])
    
# 將列表數據轉換成DataFrame格式數據,方便後續分析
wb_hot_data = pd.DataFrame(wb_hot_data, columns=['wb_rank''wb_title''wb_hot''wb_lable'])
wb_hot_data

以上,相對完整且簡潔的給大家說明白了一個簡單爬蟲的基本思路與行進路徑,希望對初學爬蟲的讀者朋友有幫助,覺得還不錯,記得點個贊哦。

推薦關注「Python 開發者」,提升 Python 技能

本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源https://mp.weixin.qq.com/s/zeJIo-pid6fvG9rOO01HnQ