一行代碼爬取微博熱搜
↑↑↑關(guān)注后"星標(biāo)"簡說Python
人人都可以簡單入門Python、爬蟲、數(shù)據(jù)分析 簡說Python推薦 來源:簡說Python 編輯:老表
作者:老表
一、前言
二、專欄概要
三、直接來:爬取微博熱搜數(shù)據(jù)
3.1 找到數(shù)據(jù)源,頁面分析
3.2 一行代碼爬取微博熱搜
3.3 爬蟲初學(xué)者看這里,爬蟲入門模板教程如何爬去微博熱搜
一、前言
大家好,我是老表,今天的分享來滿足讀者的需求,想讀“關(guān)于數(shù)據(jù)庫sql或者M(jìn)ySQL的,就那種Python來處理數(shù)據(jù)庫,比如Python爬蟲爬到數(shù)據(jù),然后封存到數(shù)據(jù)庫里面,然后再從sql里面讀取,進(jìn)行分析可視化”。

后面寫文章一方面是自己學(xué)習(xí)筆記,另外也會針對讀者需求寫一些專題文章,如果你有自己的想法,歡迎瀏覽器訪問下方鏈接,或者點(diǎn)擊閱讀原文,給博主提意見:
https://shimo.im/forms/pVQRXG6gWyqPxCTY/fill?channel=wechat
二、專欄概要
直接來:一行代碼爬取微博熱搜數(shù)據(jù) 做準(zhǔn)備:將爬取到的數(shù)據(jù)存入csv和mysql、其他數(shù)據(jù)庫 搞事情:讀取mysql數(shù)據(jù)并進(jìn)行數(shù)據(jù)分析與可視化 進(jìn)階活:將可視化數(shù)據(jù)結(jié)果呈現(xiàn)到web頁面(大屏可視化) 悄悄話:項(xiàng)目總結(jié)與思考,期待你的來稿
三、直接來:爬取微博熱搜數(shù)據(jù)
3.1 找到數(shù)據(jù)源,頁面分析
首先我們直接瀏覽器搜索微博熱搜,就可以很快的找到微博熱搜的在線頁面,地址如下:
https://s.weibo.com/top/summary/
我們要爬取的熱搜榜數(shù)據(jù),包括了如下列表中的四個(gè)字段。

話不多說,看到數(shù)據(jù)在頁面,按住F12調(diào)出瀏覽器開發(fā)者工具(推薦使用谷歌瀏覽器),然后點(diǎn)擊network,刷新頁面,在加載出來的頁面中找到summary,發(fā)現(xiàn)這個(gè)請求返回來的是頁面中的數(shù)據(jù),里面是html代碼(數(shù)據(jù)也在里面)。
然后點(diǎn)擊Headers,可以看出請求的url就是我們?yōu)g覽器里輸入的鏈接,沒有其他接口,所以,接下來就簡單了。
(本文相關(guān)全部源碼,可以在文末獲取下載地址)
3.2 一行代碼爬取微博熱搜
接下來說下簡單的數(shù)據(jù)獲取方式,只需一行代碼即可,如果硬是要算,最多就是兩行。
import pandas as pd
pd.read_html('https://s.weibo.com/top/summary/summary', index_col=0)[0]

(做這個(gè)項(xiàng)目的時(shí)候我是先用的后一種方式爬取的數(shù)據(jù))中間分析xpath路徑的時(shí)候突然發(fā)現(xiàn),這頁面上tr、td不是表格嗎,頁面上的表格爬取,在數(shù)據(jù)分析從零開始實(shí)戰(zhàn) | 基礎(chǔ)篇(四)中有詳細(xì)介紹,直接使用pandas的read_html函數(shù)即可,于是就有了上面一行代碼爬取到微博熱搜的想法了。
當(dāng)然,我們會發(fā)現(xiàn)爬取的數(shù)據(jù)還是有點(diǎn)問題,雖然已經(jīng)是DataFrame數(shù)據(jù)格式了,但是熱搜標(biāo)題和熱搜熱度由于在一個(gè)td里,所以爬取的時(shí)候也是給放到了一列中,著實(shí)有點(diǎn)尷尬。
不過沒關(guān)系,我們處理下,可以利用正則將標(biāo)題和熱度分成兩列即可。
首先對數(shù)據(jù)進(jìn)行簡單處理,設(shè)置下列名和刪除推薦熱搜(熱搜排名為'?')和置頂熱搜(熱搜排名為nan)。
# 重新設(shè)置表頭
wb_hot_data.columns = ['wb_rank', 'wb_title_hot', 'wb_lable']
# 簡單處理數(shù)據(jù),去除推薦熱搜和置頂熱搜
wb_hot_data = wb_hot_data.drop(wb_hot_data[(wb_hot_data['wb_rank']=='?') | pd.isna(wb_hot_data['wb_rank'])].index)
使用正則表達(dá)式提取數(shù)據(jù),將熱搜標(biāo)題和熱搜熱度分成兩列
import re
def reg_str(wb_title_hot='迪麗熱巴玩泡泡機(jī) 293536'):
data = re.match('(.*?) (\d+)', wb_title_hot)
if data:
return data[1],data[2]
else:
return None,None
# apply函數(shù)應(yīng)用
wb_title_hots = wb_hot_data.apply(lambda x: reg_str(x['wb_title_hot']),axis=1)
# 列表推倒式將熱搜標(biāo)題和熱搜熱度值分別賦值給兩個(gè)新列
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]
這樣數(shù)據(jù)基本就解決好啦~整體來看,還是會比后一種方法更簡單,如果你是爬蟲初學(xué)者,我建議你可以仔細(xì)看下接下來的一種數(shù)據(jù)爬取、解析方法。
3.3 爬蟲初學(xué)者看這里,爬蟲入門模板教程如何爬去微博熱搜
直接無腦套入爬蟲模板:
# 爬蟲基礎(chǔ)庫,需要提前pip install requests 安裝
import requests
# html文本解析庫,將文本內(nèi)容解析成html,方便使用xpath方式提取數(shù)據(jù)
from lxml import etree
def get_respones_data(wb_url = 'https://s.weibo.com/top/summary/'):
'''
參數(shù):wb_url 字符串 要請求的url,默認(rèn):https://s.weibo.com/top/summary/
返回:get_data,a 元組 第一個(gè)元素為請求得到的頁面文本數(shù)據(jù)(可以后期使用正則表達(dá)式提取數(shù)據(jù)) 第二個(gè)元素為將get_data文本內(nèi)容解析成html后的內(nèi)容,方便使用xpath方式提取數(shù)據(jù)
'''
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 發(fā)送請求
get_response = requests.get(wb_url,headers=headers)
# 將返回的響應(yīng)碼轉(zhuǎn)換成文本(整個(gè)網(wǎng)頁)
get_data = get_response.text
# 解析頁面
a = etree.HTML(get_data)
return get_data,a
# 調(diào)用函數(shù),獲取到數(shù)據(jù)
get_data,first_a = get_respones_data()
覺得這種方法比較麻煩的,可以跳過本部分,后面會介紹一種特別簡單的數(shù)據(jù)獲取方式(后面才想到的,之所以先記錄這種麻煩方法,也是想讓大家學(xué)習(xí)下這種方法,后面數(shù)據(jù)爬取中會比較常見)。
接下來,我們就開始從爬取到的數(shù)據(jù)中提取我們需要的數(shù)據(jù)啦!
3.3.1 熱搜標(biāo)題
首先在熱搜頁面,按住F12,調(diào)出開發(fā)者工具,點(diǎn)擊開發(fā)者工具左上角的select an element...,然后選中自己想提取的數(shù)據(jù),如下圖中的熱搜標(biāo)題。
選中并點(diǎn)擊下熱搜標(biāo)題,這是時(shí)候會回歸正常模式(非選擇元素模式),如下圖,鼠標(biāo)移動到被選中的html代碼上,然后右鍵,選擇Copy-> Copy Xpath,就可以輕松的獲取到標(biāo)題對應(yīng)的xpath路徑啦。
例如:
//*[@id="pl_top_realtimehot"]/table/tbody/tr[2]/td[2]/a
獲取到數(shù)據(jù)對應(yīng)的xpath路徑后,我們就可以調(diào)用lxml中的xpath函數(shù)進(jìn)行數(shù)據(jù)提取啦,如下代碼,輸出結(jié)果為一個(gè)列表,列表里的元素就是我們的熱搜標(biāo)題。
這里需要注意的是,我們是獲取a標(biāo)簽內(nèi)的文本內(nèi)容,所以需要在獲取的xpath路徑后在加上\text(),同樣的,如果有需要我們還可以獲取標(biāo)簽內(nèi)的元素對應(yīng)的值,如熱搜對應(yīng)的鏈接。
# 熱搜標(biāo)題
print(first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr[2]/td[2]/a/text()'))
'''
輸出:['小米放棄MI品牌']
'''
獲取到一條數(shù)據(jù)后,我們就要開始想獲取頁面所有標(biāo)題數(shù)據(jù)啦,方法也很簡單,我們按照上面的方法,在隨便獲取一個(gè)熱搜標(biāo)題的xpath路徑,然后對比一下,取相同就可以了。
如下代碼所示,我們發(fā)現(xiàn)兩個(gè)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)
看輸出數(shù)據(jù),我們會發(fā)現(xiàn)數(shù)據(jù)總數(shù)對不上,頁面上的熱搜明明只有50條,為什么我們跑出來的數(shù)據(jù)有53條?有隱藏?cái)?shù)據(jù)被我們爬出來了?
當(dāng)然不是,出現(xiàn)這種情況是因?yàn)槲⒉┯幸粋€(gè)置頂熱搜(暫且這么稱呼),另外還會有1-3個(gè)微博推薦熱搜(暫且這么稱呼),這兩種數(shù)據(jù)只有標(biāo)題屬性,沒有其他如:排行、熱度、標(biāo)簽等屬性,分析的時(shí)候需要剔除。
按上面的方法,我們可以依次獲取到熱搜熱度、熱搜排名、熱度標(biāo)簽。
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 熱度標(biāo)簽
# 熱度標(biāo)簽
'''
對比找出通用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)

這樣每個(gè)部分的數(shù)據(jù)都獲取到了,但是我們需要將每個(gè)熱搜的數(shù)據(jù)連接起來,現(xiàn)在由于里面會有置頂熱搜和微博推薦熱搜,所以有些數(shù)據(jù)沒法直接連接起來,比如熱搜標(biāo)題和熱度標(biāo)簽。
當(dāng)然,辦法肯定是有的,前面分析、復(fù)制xpath的時(shí)候,我們已經(jīng)發(fā)現(xiàn)每個(gè)xpath只有tr[n]中的n不同,所以寫個(gè)循環(huán)變動n即可,這樣每次獲取每條熱搜對應(yīng)的相關(guān)數(shù)據(jù)即可。
新問題來了,n是多少呢?顯然n不會是個(gè)定值(微博推薦熱搜條數(shù)不定),我們再仔細(xì)觀察頁面,可以發(fā)現(xiàn)不管是微博熱搜、置頂熱搜還是推薦熱搜,標(biāo)題都是有的,所以我們看標(biāo)題數(shù)即可。如下代碼。
# 通用
wb_titles = first_a.xpath('//*[@id="pl_top_realtimehot"]/table/tbody/tr/td[2]/a/text()')
n = len(wb_titles)
wb_hot_data = []
# 提取數(shù)據(jù)
def get_element(data_list):
if data_list:
return data_list[0]
else:
return None
# 遍歷循環(huán)
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)])
# 將列表數(shù)據(jù)轉(zhuǎn)換成DataFrame格式數(shù)據(jù),方便后續(xù)分析
wb_hot_data = pd.DataFrame(wb_hot_data, columns=['wb_rank', 'wb_title', 'wb_hot', 'wb_lable'])
wb_hot_data

以上,相對完整且簡潔的給大家說明白了一個(gè)簡單爬蟲的基本思路與行進(jìn)路徑,希望對初學(xué)爬蟲的讀者朋友有幫助,覺得還不錯,記得點(diǎn)個(gè)贊哦。
下一講中,我們將一起學(xué)習(xí)如何將爬取下來的數(shù)據(jù)存儲到本地csv文件,或者數(shù)據(jù)庫中(如:mysql,mongodb,sqlite等),關(guān)于數(shù)據(jù)存儲這一節(jié),你還想學(xué)習(xí)什么其他的內(nèi)容也可以在評論區(qū)、留言區(qū)進(jìn)行留言。
公眾號簡說Python學(xué)習(xí)交流群已開放,想加入進(jìn)行學(xué)習(xí)交流的讀者朋友,可以掃下方二維碼添加老表微信,回復(fù):進(jìn)群,獲取進(jìn)群邀請鏈接。
掃碼即可加我微信
觀看朋友圈,獲取最新學(xué)習(xí)資源
學(xué)習(xí)更多: 整理了我開始分享學(xué)習(xí)筆記到現(xiàn)在超過250篇優(yōu)質(zhì)文章,涵蓋數(shù)據(jù)分析、爬蟲、機(jī)器學(xué)習(xí)等方面,別再說不知道該從哪開始,實(shí)戰(zhàn)哪里找了 點(diǎn)擊閱讀原文,反饋你的建議;“點(diǎn)贊、留言”就是對我最大的支持!
