美文网首页
微信公众号python爬虫之总体概况

微信公众号python爬虫之总体概况

作者: 卧雪听月 | 来源:发表于2019-03-10 17:54 被阅读0次

这两天看公众号回顾之前的文章,有些文章发现已经被删甚至有些公众号直接被屏蔽了。甚是可惜,想着可以做一个微信公众号的爬虫来爬取文章保存到本地。

v0.1 功能

针对特定公众号已经能够实现一条龙下载功能。

  1. 获取公众号历史文章列表信息,保存;
  2. 根据公众号历史文章列表信息,进行文章下载html
  3. 将html文件转换为pdf进行保存;

整体思路

技术模块

  1. 使用requests模块,将提前分析的cookie等信息带上进行模拟get请求,获得公众号历史文章列表;
  2. 使用BeautifulSoup 下载文章;
  3. 使用pdfkit、wkhtmltopdf 来讲下载的html文件转化为pdf;

前期准备

主要涉及到对web公众号历史文章结构的分析。爬虫的思路还是从web入手,在pc机的微信app上点击公众号,之后点击在浏览器中查看。


image.png
image.png

这样就可以在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()  # 开始爬取文章

参考文献:

  1. 微信公众号爬虫 介绍了两个方法,一个是通过搜狗的公众号搜索功能,一个是微信公众号提供的搜索api。 搜狗的公众号搜索,由于想自己直接单刀直入爬取,暂时不想通过二手中间商;第二个微信公众号的api理论上应该可行,但是也要公众号账号和密码。

  2. 爬取Python教程博客并转成PDF pdfkit、BeautifulSoup 启蒙,了解pdfkit可以干html转换为 pdf 的事儿。html转pdf代码部分借鉴。

  3. 使用Python将HTML转成PDF 简单了解了pdfkit 生成pdf的三种方法从网页,从文件,从字符串

  4. 抓取微信公众号图片 专门针对微信公众号图片抓取部分的讲解,好用。解决了img筛选问题,虽然里面选取img 属性条件不正确,我这边改正为: imgs = soup.find_all('img', attrs={'data-src':True}) 可以正确筛选出文章里的配图了。

相关文章

网友评论

      本文标题:微信公众号python爬虫之总体概况

      本文链接:https://www.haomeiwen.com/subject/jbxppqtx.html