目录
- 效果
- 运行结果
- 模板中免费的部分
- 损坏的模板
- 小彩蛋
- 代码
- 问题及解决方式
- 1. 返回数据_callback({})而非json
- 2. 获取封面图链接
注: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: completeimport jsonimport requestsimport pandas as pdimport refrom time import sleepurl="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个,全部点一遍都比找出生成规律划算。因此该问题没有解决方案。