天天看點

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

作者:甘道實研

最近微網誌的瓜一個接一個,本文就将介紹如何用 Python 自動抓取微網誌熱搜,并定時發送到QQ郵箱。主要分為三部分:

  • 爬取微網誌熱搜
  • 整理資料與發送郵箱
  • 定時執行

一、抓取熱搜資料

進入微網誌熱搜榜https://s.weibo.com/top/summary後,整體頁面如下:

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

可以看到,我們需要的熱搜榜單資訊在頁面的正中央(總共50條熱搜),這裡我們需要爬取的資訊有熱搜标題、話題搜尋量、以及話題指數。按F12進入網頁源代碼頁面,點選element内容如下:

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

選中滑鼠選項,點選你要爬取的資訊,就可以看到對應的html源碼。這裡我們爬取的分為三個部分:标題、數量、指數、網址四個資訊,而我們可以從網頁源代碼發現如下規律:

資訊源代碼規律标題<a href="……" target="_blank">标題</a>數量<span>數量</span>指數<td class="td-03">指數</td>指數1<i class="……">(.*?)</i>連接配接<a href="連接配接" target="_blank">标題</a>

注意:這裡之是以有指數和指數1源代碼是因為前者擷取到的資料是有雜音的,是以需要再次用到指數1獲得最終的資訊。

之後我們運用requests包爬取網頁源代碼并通過re子產品對爬取内容進行正則提取,因為每天僅執行一次,也就不用考慮請求頭什麼的,Python代碼如下:

import requests
import re
url = 'https://s.weibo.com/top/summary?cate=realtimehot' #微網誌網址
ret = requests.get(url)
test = ret.text
u_href = '<a href="(.*?)" target="_blank">.*?</a>'
u_title = '<a href=".*?" target="_blank">(.*?)</a>'
u_amount = '<span>(.*?)</span>'
u_category = '<td class="td-03">(.*?)</td>'
u_href = '<a href="(.*?)" target="_blank">.*?</a>'
title = re.findall(u_title,test)
amount = re.findall(u_amount,test)
category = re.findall(u_category,test)
href = re.findall(u_href,test)
           

二、資料清洗

上面擷取到的title、amount、category、href四個名額是未經處理的話題、話題搜尋量、話題指數、話題連接配接。接下來我們對其進行處理,先上代碼

import pandas as pd
title = title[:-2]
title = title[1:]
href = href[:-2]
href = href[1:]
for j in range(len(href)):
    href[j] = 'https://s.weibo.com/' + href[j]
while '' in amount:
    amount.remove('')
for i in range(len(category)):
    if category[i] != '':
        category[i] = re.findall('<i class=".*?">(.*?)</i>',category[i])[0]
    if category[i] == '':
        category[i] = '空'
category = category[1:]
while '薦' in category:
    category.remove('薦')
df = pd.DataFrame()
df['關鍵詞'] = title
df['amount'] = amount
df['category'] = category
df['href'] = href
df = df.sort_values('amount')
df2 = df[df['category']=='爆']
df3 = df[df['category']=='沸']
df4 = df[df['category'] == '熱']
df5 = df[df['category'] == '新']
df6 = df[df['category'] == '空']
df = pd.concat([df2,df3,df4,df5,df6],ignore_index = True)
df.to_csv('微網誌熱搜.csv',encoding = 'gbk')#輸出為csv文本格式
           

下面對title進行處理,第一節爬取到的title是這樣的,

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

總共隻有50條熱搜,怎麼多出來3條?可以看到最後的兩條是不需要的,是以用清單提取的方法提取前50行。還有一個元素多出來?就是我們的第一個元素,即是title[0],title[0]是沒有序号與熱搜搜尋量的,如圖:

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

“天問一号成功着陸”這一話題有指數無搜尋量,是屬于缺失資料,這裡我們删除它,同樣用到清單提取元素方法。

對href連接配接的處理與title的處理相同。

接着對搜尋量做處理,采用了删除空格的語句。原因是熱搜榜中會出現推薦的話題,而推薦的話題是沒有搜尋量的,故我們删除它。

最後輪到指數處理,先看未處理前的指數,

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

上面顯而易見我們要提取的指數資訊就在每個元素裡面,同樣利用re子產品正則提取,提取出來後做三件事:

  • 去除第一個元素(原因已在title處理上講解)
  • 空字元串部分以中文空子代替
  • 去除推薦的話題

上面三步的代碼已附上。代碼裡最後的步驟就是運用pandas子產品對資料進行整理得到美觀的資料框形式。效果如下:

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

三、發郵箱與設定定時

用Python可以模拟許多大廠的郵箱發送,本文選擇常用的騰訊QQ郵箱。在此之前需要做一個準備(擷取SMTP授權碼):

登入QQ郵箱并單擊設定按鈕,然後進入賬戶這個頁面

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

進入之後向下拖動來到POP3/IMAP/SMTP/Exchange/CardDAV/CalDAV服務這欄,這裡單擊POP3/SMTP服務右側的開啟,單擊後會有一個驗證密保的過程,按照提示即可。最終會彈出一個框,裡面包含SMTP授權碼,這裡可以找個地方記錄起來,Python代碼就可以用到。

先上發送QQ郵箱的代碼模闆:

import smtplib
from email.mime.text import MIMEText
from email.mime.multipart import MIMEMultipart
number = '你的QQ郵箱号碼'
smtp = '郵箱對應的STMP授權碼'
to = '需要發送到的QQ郵箱号碼'  # 可以是非QQ的郵箱

mer = MIMEMultipart()
# 設定郵件正文内容
head = '''
<p>微網誌熱搜榜資訊</p>
<p>最熱門詞條為</p>
<p><a href="{}">{}</a></p>
<p>排名前五的熱搜</p>
<p><a href="{}">{}</a></p>
<p><a href="{}">{}</a></p>
<p><a href="{}">{}</a></p>
<p><a href="{}">{}</a></p>
<p><a href="{}">{}</a></p>
'''.format(df.iloc[0,:]['href'],df.iloc[0,:]['關鍵詞'],
           df.iloc[1,:]['href'],df.iloc[1,:]['關鍵詞'],
           df.iloc[2,:]['href'],df.iloc[2,:]['關鍵詞'],
           df.iloc[3,:]['href'],df.iloc[3,:]['關鍵詞'],
           df.iloc[4,:]['href'],df.iloc[4,:]['關鍵詞'],
           df.iloc[5,:]['href'],df.iloc[5,:]['關鍵詞'])
mer.attach(MIMEText(head, 'html', 'utf-8'))
fujian = MIMEText(open('微網誌熱搜.csv', 'rb').read(), 'base64', 'utf-8')
fujian["Content-Type"] = 'application/octet-stream'  #附件内容
fujian.add_header('Content-Disposition', 'file', filename=('utf-8', '', '微網誌熱搜.csv'))  
mer.attach(fujian)

mer['Subject'] = '每日微網誌熱搜榜單' #郵件主題
mer['From'] = number   #發送人
mer['To'] = to        #接收人

# 5.發送郵件
s = smtplib.SMTP_SSL('smtp.qq.com', 465)
s.login(number, smtp)
s.send_message(mer)  # 發送郵件
s.quit()
print('成功發送')
           

代碼架構基本如此,你需要更改的地方有如下,其餘的内容可以不改:

  • 郵件主題
  • 發送人
  • 接收人
  • SMTP授權碼
  • 附件内容

運作成功後,輸出框會有“成功發送”列印,如果你的微信綁定了你的發送QQ郵箱,那麼你就可以點選其中的附件,也就是csv檔案。

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

按照我們設定的格式,把最熱門的詞條和排名前五的詞條放入head正文内容中,效果如下:

【python 工具】利用 Python 自動抓取微網誌熱搜,并定時發送至郵箱

(這裡存在延時,是以熱搜榜和上面不一)

最後就是設定定時執行這個代碼也即是發送微網誌熱搜榜資訊,利用Schedule庫可以實作。

schedule子產品設定定時的模闆隻需改2個地方,一個是schedule.every().day.at("18:00").do(email)中的時間,一個是def函數裡面運作的内容。While True的作用就是讓程式不停止。

我們定每晚6點進行自動發送,代碼如下:

import schedule
import time
def email():
    number = '你的QQ郵箱号碼'
    smtp = '郵箱對應的STMP授權碼'
    to = '需要發送到的QQ郵箱号碼'  # 可以是非QQ的郵箱

    mer = MIMEMultipart()
    # 設定郵件正文内容
    head = '''
    <p>微網誌熱搜榜資訊</p>
    <p>最熱門詞條為</p>
    <p><a href="{}">{}</a></p>
    <p>排名前五的熱搜</p>
    <p><a href="{}">{}</a></p>
    <p><a href="{}">{}</a></p>
    <p><a href="{}">{}</a></p>
    <p><a href="{}">{}</a></p>
    <p><a href="{}">{}</a></p>
    '''.format(df.iloc[0,:]['href'],df.iloc[0,:]['關鍵詞'],
               df.iloc[1,:]['href'],df.iloc[1,:]['關鍵詞'],
               df.iloc[2,:]['href'],df.iloc[2,:]['關鍵詞'],
               df.iloc[3,:]['href'],df.iloc[3,:]['關鍵詞'],
               df.iloc[4,:]['href'],df.iloc[4,:]['關鍵詞'],
               df.iloc[5,:]['href'],df.iloc[5,:]['關鍵詞'])
    mer.attach(MIMEText(head, 'html', 'utf-8'))
    fujian = MIMEText(open('微網誌熱搜.csv', 'rb').read(), 'base64', 'utf-8')
    fujian["Content-Type"] = 'application/octet-stream'  #附件内容
    fujian.add_header('Content-Disposition', 'file', filename=('utf-8', '', '微網誌熱搜.csv'))  
    mer.attach(fujian)

    mer['Subject'] = '每日微網誌熱搜榜單' #郵件主題
    mer['From'] = number   #發送人
    mer['To'] = to        #接收人

    # 5.發送郵件
    s = smtplib.SMTP_SSL('smtp.qq.com', 465)
    s.login(number, smtp)
    s.send_message(mer)  # 發送郵件
    s.quit()
    print('成功發送')
    
schedule.every().day.at("18:00").do(email)
while True:
    schedule.run_pending()
    time.sleep(5)
           

這樣,我們就完成了利用 Python 自動爬取微網誌熱搜,并在每天指定時間自動發送整理後的結果至郵箱。