这两天看公众号回顾之前的文章,有些文章发现已经被删甚至有些公众号直接被屏蔽了。甚是可惜,想着可以做一个微信公众号的爬虫来爬取文章保存到本地。
v0.1 功能
针对特定公众号已经能够实现一条龙下载功能。
- 获取公众号历史文章列表信息,保存;
- 根据公众号历史文章列表信息,进行文章下载html
- 将html文件转换为pdf进行保存;
整体思路
技术模块
- 使用requests模块,将提前分析的cookie等信息带上进行模拟get请求,获得公众号历史文章列表;
- 使用BeautifulSoup 下载文章;
- 使用pdfkit、wkhtmltopdf 来讲下载的html文件转化为pdf;
前期准备
主要涉及到对web公众号历史文章结构的分析。爬虫的思路还是从web入手,在pc机的微信app上点击公众号,之后点击在浏览器中查看。
这样就可以在chrome上尽情分析各种请求。
主要是分析http请求query参数以及获取cookie,这样拿到信息之后可以给 requests进行模拟访问了。
基础版本,获取公众号历史文章列表:
import requests
import json
from datetime import datetime
import time
class WxMps(object):
"""微信公众号文章、评论抓取爬虫"""
def __init__(self, _biz, _pass_ticket, _app_msg_token, _cookie, _offset=0):
self.offset = _offset
self.biz = _biz # 公众号标志
self.msg_token = _app_msg_token # 票据(非固定)
self.pass_ticket = _pass_ticket # 票据(非固定)
self.headers = {
'Cookie': _cookie, # Cookie(非固定)
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.84 Safari/537.36 '
}
def start(self):
"""请求获取公众号的文章接口"""
offset = self.offset
while True:
api = 'https://mp.weixin.qq.com/mp/profile_ext?action=getmsg&__biz={0}&f=json&offset={1}' \
'&count=10&is_ok=1&scene=124&uin=777&key=777&pass_ticket={2}&wxtoken=&appmsg_token' \
'={3}&x5=1&f=json'.format(self.biz, offset, self.pass_ticket, self.msg_token)
resp = requests.get(api, headers=self.headers).json()
ret, status = resp.get('ret'), resp.get('errmsg') # 状态信息
if ret == 0 or status == 'ok':
print('Crawl article: ' + api)
offset = resp['next_offset'] # 下一次请求偏移量
general_msg_list = resp['general_msg_list']
msg_list = json.loads(general_msg_list)['list'] # 获取文章列表
for msg in msg_list:
comm_msg_info = msg['comm_msg_info'] # 该数据是本次推送多篇文章公共的
msg_id = comm_msg_info['id'] # 文章id
post_time = datetime.fromtimestamp(comm_msg_info['datetime']) # 发布时间
# msg_type = comm_msg_info['type'] # 文章类型
# msg_data = json.dumps(comm_msg_info, ensure_ascii=False) # msg原数据
app_msg_ext_info = msg.get('app_msg_ext_info') # article原数据
if app_msg_ext_info:
# 本次推送的首条文章
self._parse_articles(app_msg_ext_info, msg_id, post_time)
# 本次推送的其余文章
multi_app_msg_item_list = app_msg_ext_info.get('multi_app_msg_item_list')
if multi_app_msg_item_list:
for item in multi_app_msg_item_list:
msg_id = item['fileid'] # 文章id
if msg_id == 0:
msg_id = int(time.time() * 1000) # 设置唯一id,解决部分文章id=0出现唯一索引冲突的情况
self._parse_articles(item, msg_id, post_time)
print('next offset is %d' % offset)
else:
print('Before break , Current offset is %d' % offset)
break
def _parse_articles(self, info, msg_id, post_time):
"""解析嵌套文章数据并保存入库"""
title = info.get('title') # 标题
cover = info.get('cover') # 封面图
author = info.get('author') # 作者
digest = info.get('digest') # 关键字
source_url = info.get('source_url') # 原文地址
content_url = info.get('content_url') # 微信地址
# ext_data = json.dumps(info, ensure_ascii=False) # 原始数据
print(self._save_article(), (msg_id, title, author, cover, digest,
source_url, content_url, post_time,
datetime.now()))
@staticmethod
def _save_article():
sql = 'insert into tb_article(msg_id,title,author,cover,digest,source_url,content_url,post_time,create_time) ' \
'values(%s,%s,%s,%s,%s,%s,%s,%s,%s)'
return sql
if __name__ == '__main__':
biz = '=Mz1A2dxNTMxMTc33330MA=='
pass_ticket = '0Z0yrA+u6QYyk6KXR9u5Wenjf4xdVAi5/UndW49ZeyRLUcQ9I2F2h/'# 换成你自己的
app_msg_token = '=qdbEJ58UVyedd23POXAybNUnEnTzhrGu8g~~' # 换成你自己的
cookie = 'cookie信息粘贴'# 换成你自己的
# 以上信息不同公众号每次抓取都需要借助抓包工具做修改
wxMps = WxMps(biz, pass_ticket, app_msg_token, cookie)
wxMps.start() # 开始爬取文章
参考文献:
微信公众号爬虫 介绍了两个方法,一个是通过搜狗的公众号搜索功能,一个是微信公众号提供的搜索api。 搜狗的公众号搜索,由于想自己直接单刀直入爬取,暂时不想通过二手中间商;第二个微信公众号的api理论上应该可行,但是也要公众号账号和密码。
爬取Python教程博客并转成PDF pdfkit、BeautifulSoup 启蒙,了解pdfkit可以干html转换为 pdf 的事儿。html转pdf代码部分借鉴。
使用Python将HTML转成PDF 简单了解了pdfkit 生成pdf的三种方法从网页,从文件,从字符串
抓取微信公众号图片 专门针对微信公众号图片抓取部分的讲解,好用。解决了img筛选问题,虽然里面选取img 属性条件不正确,我这边改正为: imgs = soup.find_all('img', attrs={'data-src':True}) 可以正确筛选出文章里的配图了。