天天看點

python爬取微網誌使用者的微網誌内容和圖檔

想儲存自己喜歡的idol微網誌圖檔,但是一張張自己儲存太慢,怎麼辦?想儲存微網誌部落客的所有表情包,怎麼才能快速把這些表情包下載下傳到本地呢?想分析某位部落客的發博規律,要分析部落客所有微網誌資訊怎麼做?

python爬取微網誌使用者的微網誌内容和圖檔

這就要用到爬蟲啦,而寫爬蟲當然是用python啦,我們以移動端的劉亦菲微網誌作為實驗,之是以用移動端的微網誌,是因為爬取難度比較低,網址為移動端微網誌,打開網站,搜尋進入劉亦菲的微網誌,如下圖所示。

python爬取微網誌使用者的微網誌内容和圖檔

紅圈圈的地方那一串數字就是劉亦菲微網誌的id啦,打開 Chrome 浏覽器的調試功能,選擇 Network 菜單,觀察到擷取微網誌資料的的接口是 https://m.weibo.cn/api/xxxxxxxxxx,點選進入 就得到傳回資料的資料結構啦,如下圖所示。

python爬取微網誌使用者的微網誌内容和圖檔

但是這麼密密麻麻的代碼,誰才是我們想要的呢,難道要自己一個個去找嗎?

python爬取微網誌使用者的微網誌内容和圖檔

這裡不要擔心,我們一般需要的也就是微網誌文字、發表時間、贊評轉數和微網誌圖檔啦,我制作了一份結構樹狀圖,大家可以參考一下。

python爬取微網誌使用者的微網誌内容和圖檔

首先呢,我們建構一個基本的請求頭(因為不登入也可以獲得微網誌内容,是以不需要cookie資訊),構造請求頭的代碼如下。

host = 'm.weibo.cn'
base_url = 'https://%s/api/container/getIndex?' % host
user_agent = 'User-Agent: Mozilla/5.0 (iPhone; CPU iPhone OS 9_1 like Mac OS X) AppleWebKit/601.1.46 (KHTML, like Gecko) Version/9.0 Mobile/13B143 Safari/601.1 wechatdevtools/0.7.0 MicroMessenger/6.3.9 Language/zh_CN webview/0'#這裡的user_agent是網上找的

user_id = str(3261134763)#這串數字就是使用者id
headers = {
    'Host': host,
    'Referer': 'https://m.weibo.cn/u/%s'%user_id,
    'User-Agent': user_agent
}
           

然後import要使用的子產品

import requests
import urllib
import time
import os
import time_standard as tst
from tqdm import tqdm
from urllib.parse import urlencode
from pyquery import PyQuery as pq
           

其中time_standard子產品是自己寫的一個将微網誌created_at時間轉換為标準的‘XXXX-XX-XX’形式的日期

import datetime
def timestr_standard(time_str):
    now_time = datetime.datetime.now()
    if time_str.endswith('分鐘前') or time_str.endswith('小時前') or time_str == '剛剛':
        #strptime是把字元串轉換為時間類。strftime是把時間轉換為字元串
        time_standard = datetime.datetime.strftime(now_time.date(),'%Y-%m-%d')
    elif time_str.startswith('昨天'):
        time_standard = datetime.datetime.strftime((now_time - datetime.timedelta(days = 1)).date(),'%Y-%m-%d')
    elif time_str.startswith('0') or time_str.startswith('1'):
        time_standard = str(now_time.year) + '-' + time_str
    elif time_str.startswith('20'):
        time_standard = time_str
    return time_standard
           

建構好了請求頭并且導入了子產品就可以仿造請求得到 weibo 傳回的資料了,這邊構造一個請求函數。

def get_single_page(page):
    params = {
        'type': 'uid',
        'value': 1665372775,
        'containerid': int('107603' + user_id),#containerid就是微網誌使用者id前面加上107603
        'page': page
    }
    url = base_url + urlencode(params)
    try:
        response = requests.get(url, headers=headers)
        if response.status_code == 200:
            return response.json()
    except requests.ConnectionError as e:
        print('抓取錯誤', e.args)
           

得到傳回的資料以後,還要對傳回的資料進行解析,解析函數代碼。

# 解析頁面傳回的json資料
def analysis_page(json,pic_filebagPath):#儲存圖檔的檔案夾路徑
    items = json.get('data').get('cards')
    for item in items:
        item = item.get('mblog')
        if item:
            data = {
                'created_at': item.get('created_at'),#微網誌建立日期
                'text': pq(item.get("text")).text(),  # 僅提取内容中的文本
                'attitudes': item.get('attitudes_count'),#點贊數
                'comments': item.get('comments_count'),#評論數
                'reposts': item.get('reposts_count')#轉發數
            }
            base_data[len(base_data)] = data#把得到的資料字典存入總字典
            if pic_choice == 'y':#如果選擇儲存圖檔
                pics = item.get('pics')
                if pics:
                    for pic in pics:
                        picture_url = pic.get('large').get('url')#得到原圖位址
                        pid = pic.get('pid')#圖檔id
                        pic_name = tst.timestr_standard(data['created_at']) + '_' + pid[25:]#建構儲存圖檔檔案名,timestr_standard是一個把微網誌的created_at字元串轉換為‘XXXX-XX-XX’形式日期的一個函數
                        download_pics(picture_url,pic_name,pic_filebagPath)#下載下傳原圖
           

下載下傳圖檔的代碼下所示。

def download_pics(pic_url,pic_name,pic_filebagPath): #pic_url大圖位址,pic_name儲存圖檔的檔案名
    pic_filePath = pic_filebagPath + '\\'
    try:
        if pic_url.endswith('.jpg'):#儲存jpg圖檔
            f = open(pic_filePath + str(pic_name)+".jpg", 'wb')
        if pic_url.endswith('.gif'):#儲存gif圖檔
            f = open(pic_filePath + str(pic_name)+".gif", 'wb')
        f.write((urllib.request.urlopen(pic_url)).read())
        f.close()
    except Exception as e:
        print(pic_name+" error",e)
    time.sleep(0.1)#下載下傳間隙
           

接下來就是總程式。

if __name__ == '__main__':
    base_data = {}
    page = input('請輸入你要爬取的頁數')#可輸入爬取頁數,或者輸入‘all’爬取所有微網誌
    pic_choice = input('是否需要存儲圖檔?y/n')#選擇是否儲存圖檔
    time_start=time.time()
    try:
        json = get_single_page(1)
        screen_name = json.get('data').get('cards')[0].get('mblog').get('user').get('screen_name')#部落客昵稱
        total = json.get('data').get('cardlistInfo').get('total')#部落客微網誌總條數
        if pic_choice == 'y':#如果選擇儲存圖檔,則配置設定圖檔儲存路徑
            pic_filebagPath = 'D:\\python_project\\crawl\\weibo\\%s_picture'%screen_name
            os.makedirs(pic_filebagPath)#建立檔案夾
        else:
            pic_filebagPath = None#選擇不儲存檔案夾則不配置設定路徑
        if page == 'all':#尋找總條數
            page = total//10
            while get_single_page(page).get('ok') == 1:
                page = page + 1
            print('總頁數為:%s'%page)
        
        page = int(page) + 1
        for page in tqdm(range(1,page)):  # 抓取資料
            json = get_single_page(page)
            analysis_page(json,pic_filebagPath)
    except Exception as e:
        print('error:',e)
    finally:
        base_dataPath = 'D:\\python_project\\crawl\\weibo\\base_data_%s.txt'%screen_name#base_data儲存位址和檔案名
        f = open(base_dataPath,'w+',encoding='utf-8')
        f.write(str(base_data))
        f.close()
        time_end=time.time()
        print('\n totally cost',time_end-time_start)#顯示程式運作時間
           

程式運作狀态如下:

python爬取微網誌使用者的微網誌内容和圖檔

經過一段時間的運作,就得到了所有的微網誌資料啦。

python爬取微網誌使用者的微網誌内容和圖檔

得到的base_data字典資料。

python爬取微網誌使用者的微網誌内容和圖檔

本次内容就是這樣了,如果你覺得有幫助的話就點個贊吧!

python爬取微網誌使用者的微網誌内容和圖檔