大多數QQ模板都要黃鑽,真是好奇到底有幾個免費的,於是寫了一個爬蟲。寫的過程中遇到了一些新的問題,在此做一個記錄。 ...
目錄
註:2021/7/30做
效果
運行結果
模板中免費的部分
excel已簡單處理,可以根據順序大致找到頁碼。
一共有43個免費模板,其中39個可用,4個損壞。
損壞的模板
▽ 我以為我撿了個漏
▽ 實際上
小彩蛋
▽ “限時免費”的林丹模板
代碼
# author: shandianchengzi
# description: get templates of qq diary, saving as "qq日誌模板.xlsx". Result: 43 free, 4 damaged.
# status: complete
import json
import requests
import pandas as pd
import re
from time import sleep
url="https://h5.qzone.qq.com/proxy/domain/mall.qzone.qq.com/cgi-bin/v3/cgi_get_letter_paper"
headers={
'Accept': '*/*',
'Accept-Encoding': 'gzip, deflate, br',
'Accept-Language': 'zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6',
'Content-Type': 'application/json; charset=utf-8',
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.93 Safari/537.36 Edg/90.0.818.56',
}
headers['Cookie']="" #不需要填
params={
'mallIds':'',
'keyWord':'',
'vip':0,
'g_tk':'1002114705',
'pageNum':3,
'pageCount':5,
}
datalist = [] #用來存儲爬取的網頁信息
byYourself={
'number':5, #一次爬取的個數,建議5個,否則得到的數據會對不上
}
def LoadJson(JSON):
try:
return json.load(JSON)
except:
#找到"({"作為開始標誌 和"})"作為結束標誌之間的所有信息[jsonp格式]
return json.loads(re.match(".*?({.*}).*",JSON,re.S).group(1))
def AddData(content):
for i in content['data']['items']:
i['name']=i['mall']['name']
i['attr']=i['mall']['attr']
datalist.append(i)
#print(i)
def export_excel(export):
try:
#將字典列表轉換為DataFrame
pf = pd.DataFrame(list(export))
#指定生成的Excel表格名稱
file_path = pd.ExcelWriter('qq日誌模板.xlsx')
#替換空單元格
pf.fillna(' ', inplace=True)
#輸出
pf.to_excel(file_path, encoding='utf-8', index=False)
#保存表格
file_path.save()
print('保存成功!')
except Exception as e:
print("[-] Error = "+str(e))
print('無法導出為excel,請檢查是否未關閉同名excel文件。正在重試……')
sleep(2)
export_excel(export)
def getData(total):
try:
params['pageCount']=byYourself['number']
pageTotal=int(total/byYourself['number'])+2
print('一共要載入',pageTotal,'頁,請耐心等待:')
for i in range(1,pageTotal):
params['pageNum']=i
print('第',i,'頁,',end='')
res = requests.get(url, params=params, headers=headers)
content=LoadJson(res.text)
AddData(content)
except Exception as e:
print("[-] Error = "+str(e))
print(res.text)
print(len(datalist))
export_excel(datalist)
def myFunc():
datalist.clear()
res = requests.get(url, params=params, headers=headers)
#找到"({"作為開始標誌 和"})"作為結束標誌之間的所有信息[jsonp格式]
content=LoadJson(res.text)
total=content['data']['total']
print(total)
getData(total)
myFunc()
問題及解決方式
1. 返回數據_callback({})而非json
這種數據返回格式,使我們無法直接使用json.load(res.text)
解析。
問題根源在於JSONP
這種數據傳輸格式。
ajax請求受同源策略影響,不允許進行跨域請求,而script標簽src屬性中的鏈接卻可以訪問跨域的js腳本,利用這個特性,服務端不再返回JSON格式的數據,而是返回一段調用某個函數的js代碼,在src中進行了調用,這樣實現了跨域。
比如,可用script標簽直接指向不同域下的js腳本,在js腳本中加入這個函數。
本例中的_callback({})
便是JSONP
的典型應用。
解決方式:正則去掉_callback({})
參考https://blog.csdn.net/weixin_38208912/article/details/104208785。
def LoadJson(JSON):
try:
return json.load(JSON)
except:
#找到"({"作為開始標誌 和"})"作為結束標誌之間的所有信息[jsonp格式]
return json.loads(re.match(".*?({.*}).*",JSON,re.S).group(1))
2. 獲取封面圖鏈接
封面圖的鏈接格式:
https://qzonestyle.gtimg.cn/qzone/space_item/pre/14/108942_1.gif
找了一下規律,明顯是位置+ id + _1.gif。
可惜https://qzonestyle.gtimg.cn/qzone/space_item/pre/後面的14
不是固定的值,我暫時沒有去管它的生成規律,免費的只有39個,全部點一遍都比找出生成規律划算。因此該問題沒有解決方案。