分享

python爬虫如何实现每天爬取微信公众号的推送文章

 看见就非常 2020-01-30

上上篇文章爬虫如何爬取微信公众号文章
上篇文章python爬虫如何爬取微信公众号文章(二)

上面的文章分别介绍了如何批量获取公众号的历史文章url和如何批量爬取公众号的文章,并抽取出需要的数据保存到数据库中。

这篇文章将会介绍如何实现每天自动爬取公众号推送的文章,然后抽取出数据保存到数据库。
首先介绍一下一个微信借口wxpy,wxpy是在 itchat 的基础上,通过大量接口优化提升了模块的易用性,并进行丰富的功能扩展。
通过wxpy可以实现接收微信公众号推送的文章,但是它只实现了获取每篇文章的标题(title)摘要(summary)链接(url)封面图(cover),我在此基础上又增加了两个属性,就是文章的发布时间(pub_time)文章来源(source)

@property
    def articles(self):
        """
        公众号推送中的文章列表 (首篇的 标题/地址 与消息中的 text/url 相同)

        其中,每篇文章均有以下属性:

        * `title`: 标题
        * `summary`: 摘要
        * `url`: 文章 URL
        * `cover`: 封面或缩略图 URL
        """

        from wxpy import MP
        if self.type == SHARING and isinstance(self.sender, MP):
            tree = ETree.fromstring(self.raw['Content'])
            # noinspection SpellCheckingInspection
            items = tree.findall('.//mmreader/category/item')
            article_list = list()

            for item in items:
                def find_text(tag):

                    found = item.find(tag)
                    if found is not None:
                        return found.text

                article = Article()
                article.title = find_text('title')
                article.summary = find_text('digest')
                article.url = find_text('url')
                article.cover = find_text('cover')
                article.pub_time = find_text('pub_time')
                article.source = find_text('.//name')
                article_list.append(article)


            return article_list

在article.py中也要增加这两个属性:

# 发布时间
self.pub_time = None
# 来源
self.source = None

其实还有几个其他的一些属性,属性如下,通过ElementTree都能够获取到,具体根据自己的需求而定。

<msg>
    <appmsg appid="" sdkver="0">
        <title><![CDATA[DeepMind提图像生成的递归神经网络DRAW,158行Python代码复现]]></title>
        <des><![CDATA[本文作者基于 Eric Jang 用 158 行 Python 代码实现该系统的思路,详细阐述了 DRAW 的概念、架构和优势等。]]></des>
        <action></action>
        <type>5</type>
        <showtype>1</showtype>
        <content><![CDATA[]]></content>
        <contentattr>1</contentattr>
        <url>
            <![CDATA[http://mp.weixin.qq.com/s?__biz=MzI0ODcxODk5OA==&mid=2247507648&idx=1&sn=b5f6d0c50f3ae9388905b88d1558dfa3&chksm=e99eed39dee9642f56753a8c964efa21a89b99814680a46377f158cb736a799ccf9401ed9ff6&scene=0&xtrack=1#rd]]>
        </url>
        <lowurl><![CDATA[]]></lowurl>
        <appattach>
            <totallen>0</totallen>
            <attachid></attachid>
            <fileext></fileext>
        </appattach>
        <extinfo></extinfo>
        <mmreader>
            <category type="20" count="4">
                <name><![CDATA[AI科技大本营]]></name>
                <topnew>
                    <cover>
                        <![CDATA[https://mmbiz./mmbiz_jpg/BnSNEaficFAbkjmZ3dia6USAKQyQibt7bbPwW9miaK3vwD9Y19pRdGrRxyN6pvTlOeDL7vZxtFCDleFSIcAhdaiceUg/640?wxtype=jpeg&wxfrom=0]]>
                    </cover>
                    <width>0</width>
                    <height>0</height>
                    <digest><![CDATA[本文作者基于 Eric Jang 用 158 行 Python 代码实现该系统的思路,详细阐述了 DRAW 的概念、架构和优势等。]]></digest>
                </topnew>

                <item>
                    <itemshowtype>0</itemshowtype>
                    <title><![CDATA[DeepMind提图像生成的递归神经网络DRAW,158行Python代码复现]]></title>
                    <url>
                        <![CDATA[http://mp.weixin.qq.com/s?__biz=MzI0ODcxODk5OA==&mid=2247507648&idx=1&sn=b5f6d0c50f3ae9388905b88d1558dfa3&chksm=e99eed39dee9642f56753a8c964efa21a89b99814680a46377f158cb736a799ccf9401ed9ff6&scene=0&xtrack=1#rd]]>
                    </url>
                    <shorturl><![CDATA[]]></shorturl>
                    <longurl><![CDATA[]]></longurl>
                    <pub_time>1566993086</pub_time>
                    <cover>
                        <![CDATA[https://mmbiz./mmbiz_jpg/BnSNEaficFAbkjmZ3dia6USAKQyQibt7bbPwW9miaK3vwD9Y19pRdGrRxyN6pvTlOeDL7vZxtFCDleFSIcAhdaiceUg/640?wxtype=jpeg&wxfrom=0]]>
                    </cover>
                    <tweetid></tweetid>
                    <digest><![CDATA[本文作者基于 Eric Jang 用 158 行 Python 代码实现该系统的思路,详细阐述了 DRAW 的概念、架构和优势等。]]></digest>
                    <fileid>100020868</fileid>
                    <sources>
                        <source>
                        <name><![CDATA[AI科技大本营]]></name>
                        </source>
                    </sources>
                    <styles></styles>
                    <native_url></native_url>
                    <del_flag>0</del_flag>
                    <contentattr>1</contentattr>
                    <play_length>0</play_length>
                    <play_url><![CDATA[]]></play_url>
                    <player><![CDATA[]]></player>
                    <music_source>0</music_source>
                    <pic_num>0</pic_num>
                    <vid></vid>
                    <author><![CDATA[]]></author>
                    <recommendation><![CDATA[]]></recommendation>
                    <pic_urls></pic_urls>
                    <comment_topic_id>963025857335934976</comment_topic_id>
                    <cover_235_1>
                        <![CDATA[https://mmbiz./mmbiz_jpg/BnSNEaficFAbkjmZ3dia6USAKQyQibt7bbPwW9miaK3vwD9Y19pRdGrRxyN6pvTlOeDL7vZxtFCDleFSIcAhdaiceUg/640?wxtype=jpeg&wxfrom=0]]>
                    </cover_235_1>
                    <cover_1_1>
                        <![CDATA[https://mmbiz./mmbiz_jpg/BnSNEaficFAbkjmZ3dia6USAKQyQibt7bbP6VLGbLfXmbEjZ4p4r7QLbJopB5DewO9lmFBEb8mqzSJapD6AQeuXibg/300?wxtype=jpeg&wxfrom=0]]>
                    </cover_1_1>
                    <appmsg_like_type>2</appmsg_like_type>
                    <video_width>0</video_width>
                    <video_height>0</video_height>
                    <is_pay_subscribe>0</is_pay_subscribe>
                </item>
            </category>
            <publisher>
                <username></username>
                <nickname><![CDATA[AI科技大本营]]></nickname>
            </publisher>
            <template_header></template_header>
            <template_detail></template_detail>
            <forbid_forward>0</forbid_forward>
        </mmreader>
        <thumburl>
            <![CDATA[https://mmbiz./mmbiz_jpg/BnSNEaficFAbkjmZ3dia6USAKQyQibt7bbPwW9miaK3vwD9Y19pRdGrRxyN6pvTlOeDL7vZxtFCDleFSIcAhdaiceUg/640?wxtype=jpeg&wxfrom=0]]>
        </thumburl>
    </appmsg>
    <fromusername></fromusername>
    <appinfo>
        <version></version>
        <appname><![CDATA[AI科技大本营]]></appname>
        <isforceupdate>1</isforceupdate>
    </appinfo>


</msg>

更改完上面的代码之后,上篇文章python爬虫如何爬取微信公众号文章(二)中的实现主要逻辑的函数也需要更改一下,也就是把url地址和发布时间作为参数传进取,而不再是list类型。

    def wechat_run(self,url,pub_time):  # 实现主要逻辑

        # 打开数据库连接(ip/数据库用户名/登录密码/数据库名)
        db = pymysql.connect("localhost", "root", "root", "weixin_database")

        # 使用 cursor() 方法创建一个游标对象 cursor
        cursor = db.cursor()


        html_str = self.parse_url(url)
        content_list = self.get_content_list(html_str)
        title = ''.join(content_list[0]["title"])
        #             other1 = ''.join(content_list[0]["other"])
        other = '\n'.join(content_list[0]["other"])
        create_time = pub_time

        #             print(other)
        p1 = re.compile(r'\s*[(|(]20\d+[)|)]\s*[\u4e00-\u9fa5]*[\d]*[\u4e00-\u9fa5]+[\d]+号', re.S)
        anhao = re.search(p1, other)
        if (anhao):
            anhao = anhao.group().replace("\n", "")
        else:
            anhao = ""

        p2 = re.compile(r'\s[【]*裁判要[\u4e00-\u9fa5]\s*.*?(?=[【]|裁判文)', re.S)
        zhaiyao = ''.join(re.findall(p2, other)).replace("\n", "")
        #             print(zhaiyao)
        p3 = re.compile('<div class="rich_media_content " id="js_content">.*?</div>', re.S)
        html = re.search(p3, html_str)
        if (html):
            html = re.search(p3, html_str).group().replace("\n", "")

        else:
            html = html_str.replace("\n", "")
        sql = """INSERT INTO weixin_table(title,url,anhao,yaozhi,other,html,create_time,type_id)
            VALUES ({},{},{},{},{},{},{},{})""".format('"' + title + '"', '"' + url + '"', '"' + anhao + '"',
                                                       '"' + zhaiyao + '"', '"' + other + '"', "'" + html + "'",
                                                       create_time, 4)
        #             print(sql)
        try:
            # 执行sql语句
            cursor.execute(sql)
            # 提交到数据库执行
            db.commit()
            print("数据插入成功")
        except:
            print("数据插入失败:")
            info = sys.exc_info()
            print(info[0], ":", info[1])
            # 如果发生错误则回滚
            db.rollback()

        # 3.保存html
        page_name = title
        self.save_html(html, page_name)
        # 关闭数据库连接
        db.close()

然后写接收微信消息和公众号推送的函数:

# -*- coding: utf-8 -*-
# @Time    : 2019/8/29 上午8:31
# @Author  : jingyoushui
# @Email   : jingyoushui@163.com
# @File    : wechat.py
# @Software: PyCharm
from beijing import WeixinSpider_1
from wxpy import *
import pandas as pd
bot = Bot(cache_path=True, console_qr=True)


# 打印来自其他好友、群聊和公众号的消息
@bot.register()
def print_others(msg):
    print('msg:' + str(msg))
    articles = msg.articles
    if articles is not None:
        for article in articles:
            a = str(article.source)
            print('title:' + str(article.title))
            print('url:' + str(article.url))
            print('pub_time:' + article.pub_time)
            print('source:' + a)
            if a != "KMTV" and a != "北京行政裁判观察":
                pass
            else:
                content_list = []
                items = []
                items.append(str(article.title))
                url = str(article.url)
                items.append(url)
                pub_time = article.pub_time
                items.append(pub_time)
                content_list.append(items)
                name = ['title', 'link', 'create_time']
                test = pd.DataFrame(columns=name, data=content_list)
                if a == "KMTV":
                    test.to_csv("everyday_url/kmtv.csv", mode='a', encoding='utf-8')
                    print("保存成功")

                if a == "北京行政裁判观察":
                    test.to_csv("everyday_url/beijing.csv", mode='a', encoding='utf-8')
                    print("保存成功")
                    weixin_spider_1 = WeixinSpider_1()
                    weixin_spider_1.wechat_run(url, pub_time)

if __name__ == '__main__':
    # 堵塞线程
    bot.join()

首先获取到要爬取的公众号推送的文章的标题,url,发布时间,来源等信息,并保存到csv文件中,然后调用WeixinSpider_1类的wechat_run函数,实现对url的解析,数据的抽取,数据保存到数据库等操作。
在终端运行程序,会打印出二维码,手机微信扫描就可以登录了

运行方式是堵塞线程,可以一种处于登录状态,除非你在网页上又登录了这个账号,会被挤下来而退出。


8月30日补充:
接收公众号推送的函数可以注册是接收哪个公众号:
注册函数:

    def register(
            self, chats=None, msg_types=None,
            except_self=True, run_async=True, enabled=True
    ):
        """
        装饰器:用于注册消息配置

        :param chats: 消息所在的聊天对象:单个或列表形式的多个聊天对象或聊天类型,为空时匹配所有聊天对象
        :param msg_types: 消息的类型:单个或列表形式的多个消息类型,为空时匹配所有消息类型 (SYSTEM 类消息除外)
        :param except_self: 排除由自己发送的消息
        :param run_async: 是否异步执行所配置的函数:可提高响应速度
        :param enabled: 当前配置的默认开启状态,可事后动态开启或关闭
        """

        def do_register(func):
            self.registered.append(MessageConfig(
                bot=self, func=func, chats=chats, msg_types=msg_types,
                except_self=except_self, run_async=run_async, enabled=enabled
            ))

            return func

        return do_register

接收消息的函数可以修改为:

bot = Bot(cache_path=True, console_qr=True)
found1 = bot.mps().search('北京行政裁判观察')
print(found1)

@bot.register(found1)
def print_found1(msg):
    articles = msg.articles
    if articles is not None:
    	#一次推送可能有多篇文章
        for article in articles:
            a = str(article.source)
            print('title:' + str(article.title))
            print('url:' + str(article.url))
            print('pub_time:' + article.pub_time)
            print('source:' + a)
            content_list = []
            items = []
            #文章标题
            items.append(str(article.title))
            #文章链接
            url = str(article.url)
            items.append(url)
            #发布时间
            pub_time = article.pub_time
            items.append(pub_time)
            content_list.append(items)
            #保存到csv文件
            name = ['title', 'link', 'create_time']
            test = pd.DataFrame(columns=name, data=content_list)
            test.to_csv("everyday_url/beijing.csv", mode='a', encoding='utf-8')
            print("保存成功")
            #调用WeixinSpider_1,完成url解析,数据抽取与保存到数据库等操作
            weixin_spider_1 = WeixinSpider_1()
            weixin_spider_1.wechat_run(url, pub_time)


    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多