微信公众号专栏文章采集+首条评论(PDF格式输出)

import datetime
import json
import os
import re

from requests_html import HTMLSession
import requests
import pdfkit
import wechatsogou

confi = pdfkit.configuration(wkhtmltopdf=r"/usr/local/bin/wkhtmltopdf")

ws_api = wechatsogou.WechatSogouAPI(captcha_break_time=3)


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_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) MicroMessenger/6.8.0(0x16080000) MacWechat/3.3.1(0x13030111) Safari/605.1.15 NetType/WIF'
        }

    def dypdf(self, h1, data, comment):
        # 处理后的html
        datas = f'''
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>{h1}</title>
            </head>
            <body>
            <h2 style="text-align: center;font-weight: 400;">{h1}</h2>
            {data}
            <br>
            答案:{comment}
            </br>
            </body>
            </html>
            '''

        print("开始打印内容!")
        pdfkit.from_string(datas, h1, configuration=confi)
        print("打印保存成功!")

    def _parse_article_detail(self, content_url):
        # 从文章页提取相关参数用于获取评论,article_id是已保存的文章id
        try:
            print(self.headers)
            html = requests.get(content_url, headers=self.headers).text
        except Exception as e:
            print('获取评论失败' + content_url)
        else:
            # group(0) is current line
            str_comment = re.search(r'var comment_id = "(.*)" \|\| "(.*)" \* 1;', html)
            str_msg = re.search(r"var appmsgid = \"\" \|\| \'\' \|\| '(.*)'", html)
            str_token = re.search(r'window.appmsg_token = "(.*)";', html)

            if str_comment and str_msg and str_token:
                comment_id = str_comment.group(1)  # 评论id(固定)
                app_msg_id = str_msg.group(1)  # 票据id(非固定)
                appmsg_token = str_token.group(1)  # 票据token(非固定)

                # 缺一不可
                if appmsg_token and app_msg_id and comment_id:
                    print('Crawl article comments: ' + content_url)
                    return self._crawl_comments(app_msg_id, comment_id, appmsg_token)

    def _crawl_comments(self, app_msg_id, comment_id, appmsg_token):
        """抓取文章的评论"""

        api = 'https://mp.weixin.qq.com/mp/appmsg_comment?action=getcomment&scene=0&__biz={0}' \
              '&appmsgid={1}&idx=1&comment_id={2}&offset=0&limit=100&uin=777&key=777' \
              '&pass_ticket={3}&wxtoken=777&devicetype=android-26&clientversion=26060739' \
              '&appmsg_token={4}&x5=1&f=json'.format(self.biz, app_msg_id, comment_id,
                                                     self.pass_ticket, appmsg_token)
        resp = requests.get(api, headers=self.headers).json()
        ret, status = resp['base_resp']['ret'], resp['base_resp']['errmsg']
        if ret == 0 or status == 'ok':
            elected_comment = resp['elected_comment']
            return elected_comment[0]['content']

    def wx(self, h1, url):
        # 该方法根据文章url对html进行处理,使图片显示
        content_info = ws_api.get_article_content(url)
        # 得到html代码(代码不完整,需要加入head、body等标签)
        html_code = content_info['content_html']
        comment = self._parse_article_detail(url)
        if comment == None:
            print('没有评论')
            raise

        self.dypdf(h1, html_code, comment)

    def album_to_url(self, album_id):
        if len(album_id) > 0:
            res = []
            for i in album_id:
                url = f'https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzI3MDMxNTYwMg==&scene=1&album_id={i}'
                session = HTMLSession()
                response = session.get(url, headers=self.headers)
                name = response.html.xpath('//*[@id="js_tag_name"]/text()')[0]
                begin_msgid = \
                response.html.xpath('//*[@id="js_content_overlay"]/div[1]/div/div[5]/ul/li[1]/@data-msgid')[0]
                link = response.html.xpath('//*[@id="js_content_overlay"]/div[1]/div/div[5]/ul/li[1]/@data-link')[0]
                title = response.html.xpath('//*[@id="js_content_overlay"]/div[1]/div/div[5]/ul/li[1]/@data-title')[0]
                temp = {'album_id': i, 'begin_msgid': begin_msgid, "name": name, 'title': title, 'link': link}
                res.append(temp)
                session.close()
            return res

    def get_url(self, album_id, begin_msgid, title, link):
        count = 20
        urlList = [{'title': title, 'url': link}]
        while (1):
            url = f'https://mp.weixin.qq.com/mp/appmsgalbum?action=getalbum&__biz=MzI3MDMxNTYwMg==&album_id={album_id}&count={count}&begin_msgid={begin_msgid}&begin_itemidx=1&f=json'
            response = requests.request("GET", url, headers=self.headers)
            res = json.loads(response.text)
            try:
                sum = len(res['getalbum_resp']['article_list'])
            except:
                break
            if (sum == 20):
                begin_msgid = res['getalbum_resp']['article_list'][19]['msgid']
                urlList.extend(res['getalbum_resp']['article_list'])
                print('翻页')
            elif sum > 0:
                urlList.extend(res['getalbum_resp']['article_list'])
                break
        return urlList


if __name__ == '__main__':
    biz = 'MzI3MDMxNTYwMg=='
    pass_ticket = ''
    app_msg_token = ''
    cookie = ''
    album_id = ['1630081855687360514']
    wxMps = WxMps(biz, pass_ticket, app_msg_token, cookie)
    urls = wxMps.album_to_url(album_id)
    if len(urls) < 0:
        print('没有可爬取的')
    else:
        for i in urls:
            content_url = wxMps.get_url(i['album_id'], i['begin_msgid'], i['title'], i['link'])
            for j in content_url:
                print(i['name'], j['title'], j['url'])
                if not os.path.exists(f"./{i['name']}"):
                    os.mkdir(f"./{i['name']}")
                wxMps.wx(f"{i['name']}/{j['title']}.pdf", f"https{j['url'].split('http')[1]}")
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 194,457评论 5 459
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 81,837评论 2 371
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 141,696评论 0 319
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,183评论 1 263
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,057评论 4 355
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,105评论 1 272
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,520评论 3 381
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,211评论 0 253
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,482评论 1 290
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,574评论 2 309
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,353评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,213评论 3 312
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,576评论 3 298
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 28,897评论 0 17
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,174评论 1 250
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,489评论 2 341
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,683评论 2 335

推荐阅读更多精彩内容