想儲存自己喜歡的idol微網誌圖檔,但是一張張自己儲存太慢,怎麼辦?想儲存微網誌部落客的所有表情包,怎麼才能快速把這些表情包下載下傳到本地呢?想分析某位部落客的發博規律,要分析部落客所有微網誌資訊怎麼做?
這就要用到爬蟲啦,而寫爬蟲當然是用python啦,我們以移動端的劉亦菲微網誌作為實驗,之是以用移動端的微網誌,是因為爬取難度比較低,網址為移動端微網誌,打開網站,搜尋進入劉亦菲的微網誌,如下圖所示。
紅圈圈的地方那一串數字就是劉亦菲微網誌的id啦,打開 Chrome 浏覽器的調試功能,選擇 Network 菜單,觀察到擷取微網誌資料的的接口是 https://m.weibo.cn/api/xxxxxxxxxx,點選進入 就得到傳回資料的資料結構啦,如下圖所示。
但是這麼密密麻麻的代碼,誰才是我們想要的呢,難道要自己一個個去找嗎?
這裡不要擔心,我們一般需要的也就是微網誌文字、發表時間、贊評轉數和微網誌圖檔啦,我制作了一份結構樹狀圖,大家可以參考一下。
首先呢,我們建構一個基本的請求頭(因為不登入也可以獲得微網誌内容,是以不需要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)#顯示程式運作時間
程式運作狀态如下:
經過一段時間的運作,就得到了所有的微網誌資料啦。
得到的base_data字典資料。
本次内容就是這樣了,如果你覺得有幫助的話就點個贊吧!