Exemplo n.º 1
0
    def test_get_article_detail(self):
        file_name = os.path.join(fake_data_path, 'article_detail_backgroud-image.html')
        with io.open(file_name, encoding='utf-8') as f:
            text = f.read()

        article_detail = WechatSogouStructuring.get_article_detail(text)
        assert_equal(len(article_detail['content_img_list']), 29, article_detail)
        assert_true('data-wxurl' not in article_detail['content_html'], article_detail['content_html'])
        assert_true('qqmusic' not in article_detail['content_html'], article_detail['content_html'])
        # 图片有src属性,无data-src属性
        content_html = BeautifulSoup(article_detail['content_html'], 'lxml')
        imgs = content_html.find_all("img", src=re.compile(r'http'))
        assert_equal(len(imgs), 29, imgs)
        for img in imgs:
            assert_is_none(img.attrs.get('data-src'))

        file_name = os.path.join(fake_data_path, 'article_detail_mpvoice.html')
        with io.open(file_name, encoding='utf-8') as f:
            text = f.read()

        article_detail = WechatSogouStructuring.get_article_detail(text)
        assert_equal(len(article_detail['content_img_list']), 9, article_detail)
        assert_true('data-wxurl' not in article_detail['content_html'], article_detail['content_html'])
        assert_true('qqmusic' not in article_detail['content_html'], article_detail['content_html'])
        assert_true('mpvoice' not in article_detail['content_html'], article_detail['content_html'])

        file_name = os.path.join(fake_data_path, 'article_detail_qqmusic.html')
        with io.open(file_name, encoding='utf-8') as f:
            text = f.read()

        article_detail = WechatSogouStructuring.get_article_detail(text)
        assert_equal(len(article_detail['content_img_list']), 2, article_detail)
        assert_true('data-wxurl' not in article_detail['content_html'], article_detail['content_html'])
        assert_true('qqmusic' not in article_detail['content_html'], article_detail['content_html'])
        assert_true('mpvoice' not in article_detail['content_html'], article_detail['content_html'])

        file_name = os.path.join(fake_data_path, 'article_detail_iframe.html')
        with io.open(file_name, encoding='utf-8') as f:
            text = f.read()

        article_detail = WechatSogouStructuring.get_article_detail(text)
        assert_equal(len(article_detail['content_img_list']), 6, article_detail)
        assert_not_in('data-wxurl', article_detail['content_html'], article_detail['content_html'])
        assert_not_in('qqmusic', article_detail['content_html'], article_detail['content_html'])
        assert_not_in('mpvoice', article_detail['content_html'], article_detail['content_html'])

        # 图片有src属性,无data-src属性
        content_html = BeautifulSoup(article_detail['content_html'], 'lxml')
        iframes = content_html.find_all("iframe", src=re.compile(r'http'))
        assert_equal(len(iframes), 1, iframes)
        for iframe in iframes:
            assert_is_none(iframe.attrs.get('data-src'))
Exemplo n.º 2
0
    def get_article_content(self,
                            url,
                            del_qqmusic=True,
                            del_mpvoice=True,
                            unlock_callback=None,
                            identify_image_callback=None,
                            hosting_callback=None,
                            raw=False):
        """获取文章原文,避免临时链接失效

        Parameters
        ----------
        url : str or unicode
            原文链接,临时链接
        raw : bool
            True: 返回原始html
            False: 返回处理后的html
        del_qqmusic: bool
            True:微信原文中有插入的qq音乐,则删除
            False:微信源文中有插入的qq音乐,则保留
        del_mpvoice: bool
            True:微信原文中有插入的语音消息,则删除
            False:微信源文中有插入的语音消息,则保留
        unlock_callback : callable
            处理 文章明细 的时候出现验证码的函数,参见 unlock_callback_example
        identify_image_callback : callable
            处理 文章明细 的时候处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example
        hosting_callback: callable
            将微信采集的文章托管到7牛或者阿里云回调函数,输入微信图片源地址,返回托管后地址

        Returns
        -------
        content_html
            原文内容
        content_img_list
            文章中图片列表

        Raises
        ------
        WechatSogouRequestsException
        """

        resp = self.__get_by_unlock(
            url,
            unlock_platform=self.__unlock_wechat,
            unlock_callback=unlock_callback,
            identify_image_callback=identify_image_callback)

        resp.encoding = 'utf-8'
        if '链接已过期' in resp.text:
            raise WechatSogouException(
                'get_article_content 链接 [{}] 已过期'.format(url))
        if raw:
            return resp.text
        content_info = WechatSogouStructuring.get_article_detail(
            resp.text, del_qqmusic=del_qqmusic, del_voice=del_mpvoice)
        if hosting_callback:
            content_info = self.__hosting_wechat_img(content_info,
                                                     hosting_callback)
        return content_info
Exemplo n.º 3
0
    def test_get_gzh_by_search(self):
        file_name = os.path.join(fake_data_path, 'search-gaokao-gzh.html')
        with io.open(file_name, encoding='utf-8') as f:
            search_gaokao_gzh = f.read()

        gzh_list = WechatSogouStructuring.get_gzh_by_search(search_gaokao_gzh)

        names = []
        wechat_ids = []
        post_perms = []
        introductions = []
        authentications = []
        open_ids = []
        assert_equal(10, len(gzh_list))
        for gzh in gzh_list:
            names.append(gzh['wechat_name'])
            wechat_ids.append(gzh['wechat_id'])
            post_perms.append(gzh['post_perm'])
            introductions.append(gzh['introduction'])
            authentications.append(gzh['authentication'])
            open_ids.append(gzh['open_id'])

            assert_in('mp.weixin.qq.com/profile?src=3&timestamp=',
                      gzh['profile_url'])
            assert_in('mp.weixin.qq.com/rr?src=', gzh['qrcode'])
            assert_in('img01.sogoucdn.com/', gzh['headimage'])

        assert_equal([
            'oIWsFt6fv4FH0OBNCyoonNoAp2OM', 'oIWsFtzwnqHRVPsRY-eEzPo344jQ',
            'oIWsFt_PvlvuqFxQFPbOO26_GQh4', 'oIWsFtzpOSqygkGiyzj1vVGi2zM4',
            'oIWsFt-lCZYAtfVXRykjgsWZMoJA', 'oIWsFtzJBFA82fTPb7xU-gkPiyqA',
            'oIWsFt_wgF0dHou131y47qIMcuM0', 'oIWsFt67sO47_fHfOFQC0rBHhxcY',
            'oIWsFt5Kltl1uXsy8fhj96eIVen8', 'oIWsFt-2JeqhMEEVQuFw_geRzmbY'
        ], open_ids)
        assert_equal([
            '山东高考指南', '高考家长圈', '河南高考指南', '高考360', '云天高考', '腾讯高考', '高考快讯',
            '专业中高考教育', '晟嘉高考', '新东方在线高考辅导'
        ], names)
        assert_equal([
            u'sdgkzn', u'sinagkjzq', u'hngaokao', u'sctvgaokao360',
            u'yuntiangaokao', u'qq_gaokao', u'gkkx678', u'gh_591a43050b5f',
            u'tjsjgk', u'koogaokao'
        ], wechat_ids)
        assert_equal([-1, -1, -1, -1, -1, -1, -1, -1, -1, -1], post_perms)
        assert_equal([
            '这里是山东最权威最专业的高考交流平台,由山东商报徐玉芹教育工作室独家运作.本平台与山东商报高考交流群互为依托,为山东考生和家长提供最及时、最准确的高考政策及信息解读,以及一流的填报志愿咨询服务.合作...',
            '定期推送高三家长关注的优秀家长经验交流、志愿填报技巧、考生心理辅导方法、考前营养搭配等诸多优质内容;为家长搭建交流互动平台.',
            '发布最新高考政策,分享高效学习方法,制定高考应试策略.考点总结政策分析名校介绍高考大纲试卷解析艺考文化课,权威专业的高考资讯一手掌握.',
            '360天,360度,用心伴您升学路.四川电视台科教频道每晚7:45播出.',
            '高端教育品牌,高分考生的加油站,重点中学的合作伙伴.开阔考生视野、提升认知,在以“研究”为主线的基础上,将考生培养成一个全面型的人才.课程特色,全科协调、单科精讲.云天高考一直深受高分考生和家长的追...',
            '腾讯高考频道是中国最具互动性高考门户网站.主要为中国高考生及家长提供有价值的资讯和辅导.内容包括:新闻、评论、视频、各科辅导、志愿填报、家长指南等多方面.',
            '高考快讯平台专为考生家长提供最新高考资讯、志愿填报指南、名校排行榜、状元经验、学习方法、高分秘籍等等,我们的努力将伴随着您圆大学梦,欢迎关注阅读!',
            '旨在做最专业的中高考教育交流平台,第一时间传递权威的中高考资讯,为孩子的未来保驾护航!',
            '关于天津高考,你关注我们一个就够啦!', '提供高考资讯、高考院校库、在线答疑、政策解读及试题发布.'
        ], introductions)
        assert_equal([
            '《山东商报》社', '新浪网技术(中国)有限公司', '郑州新东方培训学校', '四川省电化教育馆(四川教育电视台)',
            '北京云天共业教育科技有限公司', '深圳市腾讯计算机系统有限公司', '广州卓越教育培训中心', '大连沙河口科苑文化培训学校',
            '天津市南开区晟嘉培训中心', '北京新东方迅程网络科技股份有限公司'
        ], authentications)
Exemplo n.º 4
0
    def get_gzh_artilce_by_history(self,
                                   keyword=None,
                                   url=None,
                                   deblocking_callback=None,
                                   identify_image_callback=None):
        if url is None:
            gzh_list = self.search_gzh(
                keyword,
                deblocking_callback=deblocking_callback,
                identify_image_callback=identify_image_callback)
            if gzh_list:
                url = gzh_list[0]['url']
            else:
                raise Exception()  # todo use ws exception

        req = requests.session()

        resp = WechatSogouRequest.get(url,
                                      req=req)  # headers=self.__set_cookie()

        if not resp.ok:
            raise WechatSogouRequestsException(
                'WechatSogouAPI get_gzh_artilce_by_history', resp)

        if '请输入验证码' in resp.text:
            self.__deblocking_history(url, resp, req, deblocking_callback,
                                      identify_image_callback)
            resp = WechatSogouRequest.get(
                url, req=req)  # req=req headers=self.__set_cookie()

        return WechatSogouStructuring.get_gzh_info_and_article_by_history(
            resp.text)
Exemplo n.º 5
0
    def test_get_article_by_search_wap(self):
        file_name = os.path.join(fake_data_path, 'search-gaokao-article.json')
        with io.open(file_name, encoding='utf-8') as f:
            wap_json = json.load(f)

        gzh_articles = WechatSogouStructuring.get_article_by_search_wap(gaokao_keyword, wap_json)
        assert_equal(10, len(gzh_articles))

        titles = []
        abstracts = []
        gzh_names = []
        isvs = []
        open_ids = []
        for i in gzh_articles:
            assert_in('gzh', i)
            assert_in('article', i)

            article = i['article']

            titles.append(article['title'])
            abstracts.append(article['abstract'])
            assert_in('mp.weixin.qq.com/', article['url'])

            gzh = i['gzh']

            assert_in('mp.weixin.qq.com/profile?src=3&timestamp', gzh['profile_url'])
            assert_in('wx.qlogo.cn/mmhead', gzh['headimage'])
            gzh_names.append(gzh['wechat_name'])
            isvs.append(gzh['isv'])
            open_ids.append(gzh['open_id'])

        assert_equal(['高考有多重要,为什么要重视高考?丨微观点',
                      '高考:穷人考不好,中产考状元,精英不高考',
                      '17个高考落榜者的“逆袭”故事:高考失败,天不会塌',
                      '刚刚,高考“满分”诞生了!(附各省高考分数线)',
                      '高考2017 | 全国各省区市高考录取时间大汇总,最新最全!',
                      '28省公布高考分数线!各省高考状元出炉!',
                      '高考2017 | 教育部发布高招录取工作通知!六大事项看过来',
                      '高考录取过程详解',
                      '高考前互有好感,高考后开始拍拖,还一同被清华录取!学霸早恋...',
                      '高考复读,你怕了吗?'],
                     titles)
        assert_equal(['针对这个问题,其实占豪已经谈过,但还是想借高考之后、借这位小战友的留言,结合自己的人生经验,谈谈个人对这件事的看法.在占豪看来,现实的社会是分层的,一个一个阶...',
                      '#条条大路通罗马,有人就出生在罗马#前几天北京文科高考状元熊轩昂接受澎湃新闻的采访的时候,说了下面这段话. “农村地区的孩子越来越难考上好学校,而像我这种父母都...',
                      '从高考分数出来的那一刻,今年的考生们大概都会大胆猜想自己未来的命运:高分者,一脚踏进名牌高校工作不愁,似乎人生已经平步青云;落榜者,面对落魄的分数整日哀叹,或...',
                      '高考会有满分的情况吗?还真有!6月22日开始,全国各省的高考成绩陆续发布.22日晚上,成都市青白江区一个小区内人声鼎沸,因为小区里有一位今年参加高考的学生,总分...',
                      '2017年高考录取工作开始了,各省区市高考录取工作何时进行?为了方便考生和家长及时了解,小编为大家作了最新最全的梳理.(图片可点击放大查看) 北京7月6日,飞行专业...',
                      '随着阅卷工作的结束,各地开始陆续公布2017年高考录取分数线.目前,已有28个省份公布了高考分数线.青海、新疆、西藏尚未公布.据媒体报道,青海将于6月30日前发布成绩...',
                      '有关省级教育行政部门、招生考试机构要精心实施减少录取批次改革,完善平行志愿投档录取办法,努力提高考生志愿满足率.上海、浙江要精心组织新高考录取工作,细化完善工...',
                      '在高考录取过程中,我省和全国各地一样都实行计算机远程网上录取的方式.录取中坚持“学校负责、招办监督”的原则,整个录取过程严格按照录取日程安排,分批次进行录取....',
                      '但学霸们在这个问题上有自己的选择,今年佛山有一对高分学霸,两人虽早有好感,但均理性选择高考后才开始拍拖,两人一同考上清华,在班上传为佳话.然而,有家长担心孩子...',
                      '我家孩子高考失利了,只考了326分,刚到本科线,本科没希望了,哎!我家闺女也是文科370分,真愁人,该怎么办呢?让孩子走专科,孩子不甘心,做家长的也不甘心,复习,...']
                     , abstracts)
        assert_equal(['占豪', '才华有限青年', '新闻哥', '光明网', '微言教育', '中国经济网', '阳光高考信息平台', '甘肃教育', '广州日报', '河北高考'], gzh_names)
        assert_equal(['0', '1', '1', '1', '1', '1', '1', '1', '1', '0'], isvs)
        assert_equal(['oIWsFt8nKJlpLQbQ5H9NMPBjxup8', 'oIWsFt24BFRU0oh5C8cGFo7vAwYk', 'oIWsFt7B8jj2BkEA1WsGkPU40uhU',
                      'oIWsFtwaY2ERrY_oAgz5pHTn4aGc', 'oIWsFt5d7GugmQYi0cNC60qYV9c4', 'oIWsFt0B7LsVbUCMpgksNY8tqIno',
                      'oIWsFtzrEz_Tydpahalp9daXMg0Y', 'oIWsFt5kk9RnueF3AiUOao2XrP9o', 'oIWsFt7aLTQfT_wmrF4GpT27_xjg',
                      'oIWsFt3nYBUhqb4beN3rTBxdUHD8'],
                     open_ids)
Exemplo n.º 6
0
    def test_get_gzh_info_and_article_by_history(self):
        file_name = os.path.join(fake_data_path, 'bitsea-history.html')
        with io.open(file_name, encoding='utf-8') as f:
            gzh_info_and_article_by_history = f.read()

        gzh_article_list = WechatSogouStructuring.get_gzh_info_and_article_by_history(gzh_info_and_article_by_history)
        assert_in('gzh', gzh_article_list)
        assert_in('article', gzh_article_list)
Exemplo n.º 7
0
    def test_get_gzh_info_and_article_by_history(self):
        file_name = os.path.join(fake_data_path, 'bitsea-history.html')
        with io.open(file_name, encoding='utf-8') as f:
            gzh_info_and_article_by_history = f.read()

        gzh_article_list = WechatSogouStructuring.get_gzh_info_and_article_by_history(
            gzh_info_and_article_by_history)
        assert_in('gzh', gzh_article_list)
        assert_in('article', gzh_article_list)
Exemplo n.º 8
0
    def test_get_article_by_history_json(self):
        file_name = os.path.join(fake_data_path, 'bitsea-history.html')
        with io.open(file_name, encoding='utf-8') as f:
            gzh_history = f.read()

        article_list = WechatSogouStructuring.get_article_by_history_json(gzh_history)
        titles = []
        urls = []
        digests = []
        for i in article_list:
            assert_equal('和菜头', i['author'])
            assert_equal('49', i['type'])
            assert_in('mp.weixin.qq.com/s?timestamp=', i['content_url'])
            assert_in(i['copyright_stat'], [11, 100])
            assert_in('mmbiz.qpic.cn/mmbiz_jpg/', i['cover'])
            assert_greater_equal(datetime.datetime.fromtimestamp(i['datetime']), datetime.datetime(2000, 1, 1))

            urls.append(i['content_url'])
            titles.append(i['title'])
            digests.append(i['abstract'])

        assert_equal(
            ['帝都深处好修行',
             '如果我有个好一点的初中英文老师',
             '【广告】让手机清凉一哈',
             '写给各位陛下',
             '可能是年度电影的《大护法》',
             '怎样决定要不要去相信一个人',
             '照亮世界的那个人',
             '《冈仁波齐》观后',
             '没有什么火候不火候的',
             '完美受害人', ],
            titles)

        assert_equal([
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbILtKInZ4hqPp3-lC1nQZcN9Fd*BGbTQp7WlZyzLvCXy0Z8yFVF*lIDlo75pemv7kW8wov4Hz5-uiVzBT5q*Nwaw=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIPsfeXemAw1IR5Pt5J*6JqjpgotoKPL*6eVHbdcbi4JCEfsnhbnsQUTLQWpBZe5UILx8062e6A2L00LyjQArkxU=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIOVd*HwElAYiJum8Q6su3tILWksr-4u9WZPSrfT7A6nErJ3f0kW8V1Jv9evurTe5X4pQrjjCZcE6WeYGwDJIH0Q=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIBtaRJpx-JbQsm-5X*GWfaS-jBtKyhOmAxio5OIROqwV71OrvtaxYq1oZG-WM9apKbLGDPIBc0sCFUB4WBOagwk=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbID-eM8BIKq1ef1ajiKO1jz1k0E6xa1ROpt2Eo3Af6OHQGfYIq-WrfEsn3jLwps1V*TXmP6443wUYgrrStzJwKPc=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIJenG0s3GyCaMQIK18U3CHsWrrGwuL5Z0X*DSoztV49L-ZPrf39mbml1GBkZnX*gueDdUJBIHgvyFsaVCTePLrI=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIE2LQ5dJqrG018DC4M7E5RQ3D4V1p*eBszVaqr2saxG864LssINc8RKcASbkdSDEMiguB9xwuMcJXgGANUpBjtg=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbINN4P-L*qGaX0SopEwmBNGbOUc*Ad5D8TKEUZOPNduI4uupwRQFL*I4r151vpRYSA92EYzb34uf82WZJMa5-kTU=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIEhfSajMgMm4uzkdEhe*6MP8H9YKg1q38xqFlBV3*sJxgwupUV8b1Q2c6OhhBEZgCTyKQvHWnGLDLBH0gvC10zQ=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIBK5p9HtcN9dTEMbIU5Vspa3IaeGox55FYOfhNbWBL2Td4hxYt3GKGzRe-TlOPVlDWXuy8CvdD1ap1fmhNt9Cy0=']
            , urls)

        assert_equal(['善哉,善哉!',
                      '说出来今天的人根本不会信,我的初中英文老师李女士在上课的时候打毛衣。',
                      '奔走相告:过气网红接到新广告!请点击,请阅读,请留言!',
                      '陛下们!微臣有话要说!',
                      '对,我就那么说了,不服来咬我啊?',
                      '在一个现代商业社会里,如何决定要不要去相信一个人?如何把人际关系判定的时间精力节省下来?网络慈父和菜头是这么说的:',
                      '在一名凡夫身上,我看到了菩萨那样的行止。',
                      '昨晚看了电影《冈仁波齐》,我不喜欢。',
                      '如果你是厨艺初学者,忘掉火候,那不是你应该关心的事情。',
                      '野鸡给自己加戏,观众不说话,并不等于看不明白。', ], digests)
Exemplo n.º 9
0
    def search_gzh(self, keyword, page=1, unlock_callback=None, identify_image_callback=None, decode_url=True):
        """搜索 公众号

        对于出现验证码的情况,可以由使用者自己提供:
            1、函数 unlock_callback ,这个函数 handle 出现验证码到解决的整个流程
            2、也可以 只提供函数 identify_image_callback,这个函数输入验证码二进制数据,输出验证码文字,剩下的由 wechatsogou 包来解决
        注意:
            函数 unlock_callback 和 identify_image_callback 只需要提供一个,如果都提供了,那么 identify_image_callback 不起作用

        Parameters
        ----------
        keyword : str or unicode
            搜索文字
        page : int, optional
            页数 the default is 1
        unlock_callback : callable
            处理出现验证码页面的函数,参见 unlock_callback_example
        identify_image_callback : callable
            处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example
        decode_url : bool
            是否解析 url

        Returns
        -------
        list[dict]
            {
                'open_id': '', # 微信号唯一ID
                'profile_url': '',  # 最近10条群发页链接
                'headimage': '',  # 头像
                'wechat_name': '',  # 名称
                'wechat_id': '',  # 微信id
                'post_perm': '',  # 最近一月群发数
                'qrcode': '',  # 二维码
                'introduction': '',  # 介绍
                'authentication': ''  # 认证
            }

        Raises
        ------
        WechatSogouRequestsException
            requests error
        """
        url = WechatSogouRequest.gen_search_gzh_url(keyword, page)
        session = requests.session()
        resp = self.__get_by_unlock(url,
                                    unlock_platform=self.__unlock_sogou,
                                    unlock_callback=unlock_callback,
                                    identify_image_callback=identify_image_callback,
                                    session=session)
        gzh_list = WechatSogouStructuring.get_gzh_by_search(resp.text)
        for i in gzh_list:
            if decode_url:
                i['profile_url'] = self.__format_url(i['profile_url'], url, resp.text, unlock_callback=unlock_callback, identify_image_callback=identify_image_callback, session=session)
            yield i
Exemplo n.º 10
0
    def search_gzh(self, keyword, page=1, unlock_callback=None, identify_image_callback=None, decode_url=True):
        """搜索 公众号

        对于出现验证码的情况,可以由使用者自己提供:
            1、函数 unlock_callback ,这个函数 handle 出现验证码到解决的整个流程
            2、也可以 只提供函数 identify_image_callback,这个函数输入验证码二进制数据,输出验证码文字,剩下的由 wechatsogou 包来解决
        注意:
            函数 unlock_callback 和 identify_image_callback 只需要提供一个,如果都提供了,那么 identify_image_callback 不起作用

        Parameters
        ----------
        keyword : str or unicode
            搜索文字
        page : int, optional
            页数 the default is 1
        unlock_callback : callable
            处理出现验证码页面的函数,参见 unlock_callback_example
        identify_image_callback : callable
            处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example
        decode_url : bool
            是否解析 url

        Returns
        -------
        list[dict]
            {
                'open_id': '', # 微信号唯一ID
                'profile_url': '',  # 最近10条群发页链接
                'headimage': '',  # 头像
                'wechat_name': '',  # 名称
                'wechat_id': '',  # 微信id
                'post_perm': '',  # 最近一月群发数
                'qrcode': '',  # 二维码
                'introduction': '',  # 介绍
                'authentication': ''  # 认证
            }

        Raises
        ------
        WechatSogouRequestsException
            requests error
        """
        url = WechatSogouRequest.gen_search_gzh_url(keyword, page)
        session = requests.session()
        resp = self.__get_by_unlock(url,
                                    unlock_platform=self.__unlock_sogou,
                                    unlock_callback=unlock_callback,
                                    identify_image_callback=identify_image_callback,
                                    session=session)
        gzh_list = WechatSogouStructuring.get_gzh_by_search(resp.text)
        for i in gzh_list:
            if decode_url:
                i['profile_url'] = self.__format_url(i['profile_url'], url, resp.text, unlock_callback=unlock_callback, identify_image_callback=identify_image_callback, session=session)
            yield i
Exemplo n.º 11
0
    def test_get_gzh_info_by_history(self):
        file_name = os.path.join(fake_data_path, 'bitsea-history.html')
        with io.open(file_name, encoding='utf-8') as f:
            gzh_history = f.read()

        gzh_info = WechatSogouStructuring.get_gzh_info_by_history(gzh_history)

        assert_equal('槽边往事', gzh_info['wechat_name'])
        assert_equal('bitsea', gzh_info['wechat_id'])
        assert_equal('和菜头的微信Blog,用于分享各种新鲜资讯', gzh_info['authentication'])
        assert_equal('http://wx.qlogo.cn/mmhead/Q3auHgzwzM6zmSwQkvHdgXDtnpAyLYjuib8QdW6ibKKGo8zcZVbYxiaUw/0',
                     gzh_info['headimage'])
        assert_equal(' ', gzh_info['introduction'])
Exemplo n.º 12
0
    def get_article_content(self, url, del_qqmusic=True, del_mpvoice=True, unlock_callback=None,
                            identify_image_callback=None, hosting_callback=None, raw=False):
        """获取文章原文,避免临时链接失效

        Parameters
        ----------
        url : str or unicode
            原文链接,临时链接
        raw : bool
            True: 返回原始html
            False: 返回处理后的html
        del_qqmusic: bool
            True:微信原文中有插入的qq音乐,则删除
            False:微信源文中有插入的qq音乐,则保留
        del_mpvoice: bool
            True:微信原文中有插入的语音消息,则删除
            False:微信源文中有插入的语音消息,则保留
        unlock_callback : callable
            处理 文章明细 的时候出现验证码的函数,参见 unlock_callback_example
        identify_image_callback : callable
            处理 文章明细 的时候处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example
        hosting_callback: callable
            将微信采集的文章托管到7牛或者阿里云回调函数,输入微信图片源地址,返回托管后地址

        Returns
        -------
        content_html
            原文内容
        content_img_list
            文章中图片列表

        Raises
        ------
        WechatSogouRequestsException
        """

        resp = self.__get_by_unlock(url,
                                    unlock_platform=self.__unlock_wechat,
                                    unlock_callback=unlock_callback,
                                    identify_image_callback=identify_image_callback)

        resp.encoding = 'utf-8'
        if '链接已过期' in resp.text:
            raise WechatSogouException('get_article_content 链接 [{}] 已过期'.format(url))
        if raw:
            return resp.text
        content_info = WechatSogouStructuring.get_article_detail(resp.text, del_qqmusic=del_qqmusic,
                                                                 del_voice=del_mpvoice)
        if hosting_callback:
            content_info = self.__hosting_wechat_img(content_info, hosting_callback)
        return content_info
Exemplo n.º 13
0
    def test_get_gzh_info_by_history(self):
        file_name = os.path.join(fake_data_path, 'bitsea-history.html')
        with io.open(file_name, encoding='utf-8') as f:
            gzh_history = f.read()

        gzh_info = WechatSogouStructuring.get_gzh_info_by_history(gzh_history)

        assert_equal('槽边往事', gzh_info['wechat_name'])
        assert_equal('bitsea', gzh_info['wechat_id'])
        assert_equal('和菜头的微信Blog,用于分享各种新鲜资讯', gzh_info['authentication'])
        assert_equal(
            'http://wx.qlogo.cn/mmhead/Q3auHgzwzM6zmSwQkvHdgXDtnpAyLYjuib8QdW6ibKKGo8zcZVbYxiaUw/0',
            gzh_info['headimage'])
        assert_equal(' ', gzh_info['introduction'])
Exemplo n.º 14
0
    def get_gzh_artilce_by_hot(self,
                               hot_index,
                               page=1,
                               unlock_callback=None,
                               identify_image_callback=None):
        """获取 首页热门文章

        Parameters
        ----------
        hot_index : WechatSogouConst.hot_index
            首页热门文章的分类(常量):WechatSogouConst.hot_index.xxx
        page : int
            页数

        Returns
        -------
        list[dict]
            {
                'gzh': {
                    'headimage': str,  # 公众号头像
                    'wechat_name': str,  # 公众号名称
                },
                'article': {
                    'url': str,  # 文章临时链接
                    'title': str,  # 文章标题
                    'abstract': str,  # 文章摘要
                    'time': int,  # 推送时间,10位时间戳
                    'open_id': str,  # open id
                    'main_img': str  # 封面图片
                }
            }
        """

        assert hasattr(WechatSogouConst.hot_index, hot_index)
        assert isinstance(page, int) and page > 0

        url = WechatSogouRequest.gen_hot_url(hot_index, page)
        resp = self.__get_by_unlock(
            url,
            is_need_unlock=lambda x: 'antispider' in x.url,
            unlock_platform=self.__unlock_sogou,
            unlock_callback=unlock_callback,
            identify_image_callback=identify_image_callback)

        resp.encoding = 'utf-8'
        return WechatSogouStructuring.get_gzh_artilce_by_hot(resp.text)
Exemplo n.º 15
0
    def get_gzh_artilce_by_hot(self, hot_index, page=1, unlock_callback=None, identify_image_callback=None):
        """获取 首页热门文章

        Parameters
        ----------
        hot_index : WechatSogouConst.hot_index
            首页热门文章的分类(常量):WechatSogouConst.hot_index.xxx
        page : int
            页数

        Returns
        -------
        list[dict]
            {
                'gzh': {
                    'headimage': str,  # 公众号头像
                    'wechat_name': str,  # 公众号名称
                },
                'article': {
                    'url': str,  # 文章临时链接
                    'title': str,  # 文章标题
                    'abstract': str,  # 文章摘要
                    'time': int,  # 推送时间,10位时间戳
                    'open_id': str,  # open id
                    'main_img': str  # 封面图片
                }
            }
        """

        assert hasattr(WechatSogouConst.hot_index, hot_index)
        assert isinstance(page, int) and page > 0

        url = WechatSogouRequest.gen_hot_url(hot_index, page)
        resp = self.__get_by_unlock(url,
                                    is_need_unlock=lambda x: 'antispider' in x.url,
                                    unlock_platform=self.__unlock_sogou,
                                    unlock_callback=unlock_callback,
                                    identify_image_callback=identify_image_callback)

        resp.encoding = 'utf-8'
        return WechatSogouStructuring.get_gzh_artilce_by_hot(resp.text)
Exemplo n.º 16
0
    def test_get_article_by_search_wap(self):
        file_name = os.path.join(fake_data_path, 'search-gaokao-article.json')
        with io.open(file_name, encoding='utf-8') as f:
            wap_json = json.load(f)

        gzh_artilces = WechatSogouStructuring.get_article_by_search_wap(
            gaokao_keyword, wap_json)
        assert_equal(10, len(gzh_artilces))

        titles = []
        abstracts = []
        gzh_names = []
        isvs = []
        open_ids = []
        for i in gzh_artilces:
            assert_in('gzh', i)
            assert_in('article', i)

            article = i['article']

            titles.append(article['title'])
            abstracts.append(article['abstract'])
            assert_in('mp.weixin.qq.com/', article['url'])

            gzh = i['gzh']

            assert_in('mp.weixin.qq.com/profile?src=3&timestamp',
                      gzh['profile_url'])
            assert_in('wx.qlogo.cn/mmhead', gzh['headimage'])
            gzh_names.append(gzh['wechat_name'])
            isvs.append(gzh['isv'])
            open_ids.append(gzh['open_id'])

        assert_equal([
            '高考有多重要,为什么要重视高考?丨微观点', '高考:穷人考不好,中产考状元,精英不高考',
            '17个高考落榜者的“逆袭”故事:高考失败,天不会塌', '刚刚,高考“满分”诞生了!(附各省高考分数线)',
            '高考2017 | 全国各省区市高考录取时间大汇总,最新最全!', '28省公布高考分数线!各省高考状元出炉!',
            '高考2017 | 教育部发布高招录取工作通知!六大事项看过来', '高考录取过程详解',
            '高考前互有好感,高考后开始拍拖,还一同被清华录取!学霸早恋...', '高考复读,你怕了吗?'
        ], titles)
        assert_equal([
            '针对这个问题,其实占豪已经谈过,但还是想借高考之后、借这位小战友的留言,结合自己的人生经验,谈谈个人对这件事的看法.在占豪看来,现实的社会是分层的,一个一个阶...',
            '#条条大路通罗马,有人就出生在罗马#前几天北京文科高考状元熊轩昂接受澎湃新闻的采访的时候,说了下面这段话. “农村地区的孩子越来越难考上好学校,而像我这种父母都...',
            '从高考分数出来的那一刻,今年的考生们大概都会大胆猜想自己未来的命运:高分者,一脚踏进名牌高校工作不愁,似乎人生已经平步青云;落榜者,面对落魄的分数整日哀叹,或...',
            '高考会有满分的情况吗?还真有!6月22日开始,全国各省的高考成绩陆续发布.22日晚上,成都市青白江区一个小区内人声鼎沸,因为小区里有一位今年参加高考的学生,总分...',
            '2017年高考录取工作开始了,各省区市高考录取工作何时进行?为了方便考生和家长及时了解,小编为大家作了最新最全的梳理.(图片可点击放大查看) 北京7月6日,飞行专业...',
            '随着阅卷工作的结束,各地开始陆续公布2017年高考录取分数线.目前,已有28个省份公布了高考分数线.青海、新疆、西藏尚未公布.据媒体报道,青海将于6月30日前发布成绩...',
            '有关省级教育行政部门、招生考试机构要精心实施减少录取批次改革,完善平行志愿投档录取办法,努力提高考生志愿满足率.上海、浙江要精心组织新高考录取工作,细化完善工...',
            '在高考录取过程中,我省和全国各地一样都实行计算机远程网上录取的方式.录取中坚持“学校负责、招办监督”的原则,整个录取过程严格按照录取日程安排,分批次进行录取....',
            '但学霸们在这个问题上有自己的选择,今年佛山有一对高分学霸,两人虽早有好感,但均理性选择高考后才开始拍拖,两人一同考上清华,在班上传为佳话.然而,有家长担心孩子...',
            '我家孩子高考失利了,只考了326分,刚到本科线,本科没希望了,哎!我家闺女也是文科370分,真愁人,该怎么办呢?让孩子走专科,孩子不甘心,做家长的也不甘心,复习,...'
        ], abstracts)
        assert_equal([
            '占豪', '才华有限青年', '新闻哥', '光明网', '微言教育', '中国经济网', '阳光高考信息平台', '甘肃教育',
            '广州日报', '河北高考'
        ], gzh_names)
        assert_equal(['0', '1', '1', '1', '1', '1', '1', '1', '1', '0'], isvs)
        assert_equal([
            'oIWsFt8nKJlpLQbQ5H9NMPBjxup8', 'oIWsFt24BFRU0oh5C8cGFo7vAwYk',
            'oIWsFt7B8jj2BkEA1WsGkPU40uhU', 'oIWsFtwaY2ERrY_oAgz5pHTn4aGc',
            'oIWsFt5d7GugmQYi0cNC60qYV9c4', 'oIWsFt0B7LsVbUCMpgksNY8tqIno',
            'oIWsFtzrEz_Tydpahalp9daXMg0Y', 'oIWsFt5kk9RnueF3AiUOao2XrP9o',
            'oIWsFt7aLTQfT_wmrF4GpT27_xjg', 'oIWsFt3nYBUhqb4beN3rTBxdUHD8'
        ], open_ids)
Exemplo n.º 17
0
    def test_get_gzh_article_by_hot(self):
        file_name = os.path.join(fake_data_path, 'wapindex-wap-0612-wap_8-0.html')
        with io.open(file_name, encoding='utf-8') as f:
            gzh_article_by_hot = f.read()

            gzh_articles = WechatSogouStructuring.get_gzh_article_by_hot(gzh_article_by_hot)

        for gzh_article in gzh_articles:
            assert_in('gzh', gzh_article)
            assert_in('article', gzh_article)
            assert_in('http://mp.weixin.qq.com/s?src=', gzh_article['article']['url'])
        assert_greater_equal(len(gzh_articles), 10)

        wechat_names = []
        headimages = []
        titles = []
        times = []
        for i in gzh_articles:
            wechat_names.append(i['gzh']['wechat_name'])
            headimages.append(i['gzh']['headimage'])
            titles.append(i['article']['title'])
            times.append(i['article']['time'])

        assert_equal(
            ['全球汽车精选', '车早茶', '吴佩频道', '驾考宝典', '腾讯汽车', '新车评', '非常好车', '汽车情报所',
             '一猫汽车资讯', '资深科技控', '郎club', '科技日报', '汽车使用宝典', '名车报', '科普中国网'],
            wechat_names)
        assert_equal(['http://img03.sogoucdn.com/app/a/100520090/oIWsFt1dGMefD1f8dOg2UCwQUjKs',
                      'http://img04.sogoucdn.com/app/a/100520090/oIWsFtwoQX8wX7w6loDevPqLEC_I',
                      'http://img03.sogoucdn.com/app/a/100520090/oIWsFt9Hbbtr9VLnfR9i_K5Z8D48',
                      'http://img04.sogoucdn.com/app/a/100520090/oIWsFt3txmWu-usvUa6gU0qlyEVo',
                      'http://img01.sogoucdn.com/app/a/100520090/oIWsFt8VDujUqNSCfruXtMNfekaw',
                      'http://img01.sogoucdn.com/app/a/100520090/oIWsFt9YD5HWLDe5QAkuvh0JWrgw',
                      'http://img01.sogoucdn.com/app/a/100520090/oIWsFt_WUnpQ7lZajAstgL8o1lWo',
                      'http://img02.sogoucdn.com/app/a/100520090/oIWsFtzUnzWUMz1PMek5zjVlS42U',
                      'http://img03.sogoucdn.com/app/a/100520090/oIWsFt2yk491dhhSP940JzLEameY',
                      'http://img03.sogoucdn.com/app/a/100520090/oIWsFtzm9UtmgY-SkOTFwQFpGsU8',
                      'http://img02.sogoucdn.com/app/a/100520090/oIWsFt7VwiM8GqYcv8DBNb-k5NBQ',
                      'http://img03.sogoucdn.com/app/a/100520090/oIWsFt2tjckivF8b0MP_nNTdESkE',
                      'http://img01.sogoucdn.com/app/a/100520090/oIWsFtzC2r61_riTCWp5iHX04fmo',
                      'http://img02.sogoucdn.com/app/a/100520090/oIWsFt8JIY_-o7DBMxorP19hcF0Q',
                      'http://img04.sogoucdn.com/app/a/100520090/oIWsFtyV5sdIXU2uy4m6oVBq77nA'],
                     headimages)
        assert_equal(['不做这个动作,你的轮胎3个月就要换!',
                      '新车质量最差的十个品牌?国人表示难以接受……',
                      '带着米其林的指引去看古德伍德|品牌',
                      '方向盘打法巧记口诀,科目二提分就靠它了!',
                      '宝马“鸡腿”、奥迪“游艇”,这些奇葩的挡杆你见过几个?',
                      '你没看错,我们做了期途昂和途锐的对比',
                      '7成特斯拉被召回,难道是质量不过关?',
                      '在中国惹不起的7种车,遇到请回避!',
                      '迈腾摊上大事儿了 全新一代君威17.58万起', '面对这份驾享,朝廷大人都忍不住亲自上阵!',
                      '外卖小哥被暴晒:底层人士的悲哀,有钱人不会懂',
                      '自动驾驶还处于“新手”阶段,何时成为“老司机”?院士这样说……',
                      '高速上碰到石头,是躲还是撞?', '装什么神秘,不就是加长版的讴歌TLX吗!',
                      '一个动作,车里的人集体中毒!很多人都忽略了'],
                     titles)
        assert_equal(
            [1501328135, 1501327941, 1501326826, 1501326716, 1501326675, 1501326455, 1501326222, 1501325595,
             1501325529, 1501325521, 1501325223, 1501324531, 1501324443, 1501324310, 1501323274],
            times)
Exemplo n.º 18
0
    def test_get_article_detail(self):
        file_name = os.path.join(fake_data_path,
                                 'article_detail_backgroud-image.html')
        with io.open(file_name, encoding='utf-8') as f:
            text = f.read()

        article_detail = WechatSogouStructuring.get_article_detail(text)
        assert_equal(len(article_detail['content_img_list']), 29,
                     article_detail)
        assert_true('data-wxurl' not in article_detail['content_html'],
                    article_detail['content_html'])
        assert_true('qqmusic' not in article_detail['content_html'],
                    article_detail['content_html'])
        # 图片有src属性,无data-src属性
        content_html = BeautifulSoup(article_detail['content_html'], 'lxml')
        imgs = content_html.find_all("img", src=re.compile(r'http'))
        assert_equal(len(imgs), 29, imgs)
        for img in imgs:
            assert_is_none(img.attrs.get('data-src'))

        file_name = os.path.join(fake_data_path, 'article_detail_mpvoice.html')
        with io.open(file_name, encoding='utf-8') as f:
            text = f.read()

        article_detail = WechatSogouStructuring.get_article_detail(text)
        assert_equal(len(article_detail['content_img_list']), 9,
                     article_detail)
        assert_true('data-wxurl' not in article_detail['content_html'],
                    article_detail['content_html'])
        assert_true('qqmusic' not in article_detail['content_html'],
                    article_detail['content_html'])
        assert_true('mpvoice' not in article_detail['content_html'],
                    article_detail['content_html'])

        file_name = os.path.join(fake_data_path, 'article_detail_qqmusic.html')
        with io.open(file_name, encoding='utf-8') as f:
            text = f.read()

        article_detail = WechatSogouStructuring.get_article_detail(text)
        assert_equal(len(article_detail['content_img_list']), 2,
                     article_detail)
        assert_true('data-wxurl' not in article_detail['content_html'],
                    article_detail['content_html'])
        assert_true('qqmusic' not in article_detail['content_html'],
                    article_detail['content_html'])
        assert_true('mpvoice' not in article_detail['content_html'],
                    article_detail['content_html'])

        file_name = os.path.join(fake_data_path, 'article_detail_iframe.html')
        with io.open(file_name, encoding='utf-8') as f:
            text = f.read()

        article_detail = WechatSogouStructuring.get_article_detail(text)
        assert_equal(len(article_detail['content_img_list']), 6,
                     article_detail)
        assert_not_in('data-wxurl', article_detail['content_html'],
                      article_detail['content_html'])
        assert_not_in('qqmusic', article_detail['content_html'],
                      article_detail['content_html'])
        assert_not_in('mpvoice', article_detail['content_html'],
                      article_detail['content_html'])

        # 图片有src属性,无data-src属性
        content_html = BeautifulSoup(article_detail['content_html'], 'lxml')
        iframes = content_html.find_all("iframe", src=re.compile(r'http'))
        assert_equal(len(iframes), 1, iframes)
        for iframe in iframes:
            assert_is_none(iframe.attrs.get('data-src'))
Exemplo n.º 19
0
    def test_get_gzh_by_search(self):
        file_name = os.path.join(fake_data_path, 'search-gaokao-gzh.html')
        with io.open(file_name, encoding='utf-8') as f:
            search_gaokao_gzh = f.read()

        gzh_list = WechatSogouStructuring.get_gzh_by_search(search_gaokao_gzh)

        names = []
        wechat_ids = []
        post_perms = []
        introductions = []
        authentications = []
        open_ids = []
        assert_equal(10, len(gzh_list))
        for gzh in gzh_list:
            names.append(gzh['wechat_name'])
            wechat_ids.append(gzh['wechat_id'])
            post_perms.append(gzh['post_perm'])
            introductions.append(gzh['introduction'])
            authentications.append(gzh['authentication'])
            open_ids.append(gzh['open_id'])

            assert_in('mp.weixin.qq.com/profile?src=3&timestamp=', gzh['profile_url'])
            assert_in('mp.weixin.qq.com/rr?src=', gzh['qrcode'])
            assert_in('img01.sogoucdn.com/', gzh['headimage'])

        assert_equal(['oIWsFt6fv4FH0OBNCyoonNoAp2OM',
                      'oIWsFtzwnqHRVPsRY-eEzPo344jQ',
                      'oIWsFt_PvlvuqFxQFPbOO26_GQh4',
                      'oIWsFtzpOSqygkGiyzj1vVGi2zM4',
                      'oIWsFt-lCZYAtfVXRykjgsWZMoJA',
                      'oIWsFtzJBFA82fTPb7xU-gkPiyqA',
                      'oIWsFt_wgF0dHou131y47qIMcuM0',
                      'oIWsFt67sO47_fHfOFQC0rBHhxcY',
                      'oIWsFt5Kltl1uXsy8fhj96eIVen8',
                      'oIWsFt-2JeqhMEEVQuFw_geRzmbY'],
                     open_ids)
        assert_equal(['山东高考指南',
                      '高考家长圈',
                      '河南高考指南',
                      '高考360',
                      '云天高考',
                      '腾讯高考',
                      '高考快讯',
                      '专业中高考教育',
                      '晟嘉高考',
                      '新东方在线高考辅导'],
                     names)
        assert_equal([u'sdgkzn',
                      u'sinagkjzq',
                      u'hngaokao',
                      u'sctvgaokao360',
                      u'yuntiangaokao',
                      u'qq_gaokao',
                      u'gkkx678',
                      u'gh_591a43050b5f',
                      u'tjsjgk',
                      u'koogaokao'],
                     wechat_ids)
        assert_equal([-1, -1, -1, -1, -1, -1, -1, -1, -1, -1], post_perms)
        assert_equal(
            ['这里是山东最权威最专业的高考交流平台,由山东商报徐玉芹教育工作室独家运作.本平台与山东商报高考交流群互为依托,为山东考生和家长提供最及时、最准确的高考政策及信息解读,以及一流的填报志愿咨询服务.合作...',
             '定期推送高三家长关注的优秀家长经验交流、志愿填报技巧、考生心理辅导方法、考前营养搭配等诸多优质内容;为家长搭建交流互动平台.',
             '发布最新高考政策,分享高效学习方法,制定高考应试策略.考点总结政策分析名校介绍高考大纲试卷解析艺考文化课,权威专业的高考资讯一手掌握.',
             '360天,360度,用心伴您升学路.四川电视台科教频道每晚7:45播出.',
             '高端教育品牌,高分考生的加油站,重点中学的合作伙伴.开阔考生视野、提升认知,在以“研究”为主线的基础上,将考生培养成一个全面型的人才.课程特色,全科协调、单科精讲.云天高考一直深受高分考生和家长的追...',
             '腾讯高考频道是中国最具互动性高考门户网站.主要为中国高考生及家长提供有价值的资讯和辅导.内容包括:新闻、评论、视频、各科辅导、志愿填报、家长指南等多方面.',
             '高考快讯平台专为考生家长提供最新高考资讯、志愿填报指南、名校排行榜、状元经验、学习方法、高分秘籍等等,我们的努力将伴随着您圆大学梦,欢迎关注阅读!',
             '旨在做最专业的中高考教育交流平台,第一时间传递权威的中高考资讯,为孩子的未来保驾护航!',
             '关于天津高考,你关注我们一个就够啦!',
             '提供高考资讯、高考院校库、在线答疑、政策解读及试题发布.'],
            introductions)
        assert_equal(['《山东商报》社',
                      '新浪网技术(中国)有限公司',
                      '郑州新东方培训学校',
                      '四川省电化教育馆(四川教育电视台)',
                      '北京云天共业教育科技有限公司',
                      '深圳市腾讯计算机系统有限公司',
                      '广州卓越教育培训中心',
                      '大连沙河口科苑文化培训学校',
                      '天津市南开区晟嘉培训中心',
                      '北京新东方迅程网络科技股份有限公司'],
                     authentications)
Exemplo n.º 20
0
 def get_target_list_v2(self, target):
     page = 10
     keyword = target['jobTypeName']
     target['items'] = []
     target['main_url'] = []
     first_data = 'init_proxy'
     for i in range(page):
         while True:
             url = u'http://weixin.sogou.com/weixin?type=2&page=%s&ie=utf8&query=%s&interation=' % (
                 i + 1, parse.quote(keyword))
             self.headers['Referer'] = url
             self.headers['Cookie'] = 'SUV="";SNUID="";'
             if url not in self.saved_data_list:
                 try:
                     self.logger.debug("queue get before size:%s" %
                                       q_proxies.qsize())
                     proxies = q_proxies.get()
                     self.logger.debug("queue get after size :%s" %
                                       q_proxies.qsize())
                     resp = requests.get(
                         url,
                         proxies=proxies,
                         headers=self.headers,
                         timeout=8,
                     )
                     if resp.ok:
                         if u'antispider' in resp.url:
                             # TODO:记录一下被识别为爬虫的代理IP到数据库 #
                             self.proxies_table.create(
                                 object=proxies['http'], )
                             self.logger.debug(
                                 u'Name: %s, Page: %s, DetachAntiSpider: %s'
                                 % (keyword, str(i + 1), proxies['http']))
                             first_data = 'detach_spider'
                             continue
                         else:
                             time.sleep(random.randint(2, 5))
                             target_little_list = WechatSogouStructuring.get_article_by_search(
                                 resp.text)
                             if target_little_list.__len__() == 0:
                                 break  # break for the page doesnt have data
                             target['items'].append(target_little_list)
                             target['main_url'].append(url)
                             self.logger.debug(
                                 'get item %s page %d total %d ' %
                                 (keyword, i + 1,
                                  target_little_list.__len__()))
                             break  # break for success
                     else:
                         self.logger.debug(
                             u'Name: %s, Page: %s, HttpError: %s' %
                             (keyword, str(i + 1), str(resp.status_code)))
                         first_data = 'http_error'
                 except Exception as e:
                     self.logger.debug(u'Name: %s, Page: %s, Error: %s' %
                                       (keyword, i + 1, type(e)))
                     first_data = 'catch_exception'
             else:
                 self.logger.debug('the url had been crawled')
                 break  # break for exist
     self.logger.debug(u'Name: %s, Total: %s' %
                       (keyword, len(target['items'])))
     return target
Exemplo n.º 21
0
    def search_article(self, keyword, page=1, timesn=WechatSogouConst.search_article_time.anytime,
                       article_type=WechatSogouConst.search_article_type.all, ft=None, et=None,
                       unlock_callback=None,
                       identify_image_callback=None,
                       decode_url=True):
        """搜索 文章

        对于出现验证码的情况,可以由使用者自己提供:
            1、函数 unlock_callback ,这个函数 handle 出现验证码到解决的整个流程
            2、也可以 只提供函数 identify_image_callback,这个函数输入验证码二进制数据,输出验证码文字,剩下的由 wechatsogou 包来解决
        注意:
            函数 unlock_callback 和 identify_image_callback 只需要提供一个,如果都提供了,那么 identify_image_callback 不起作用

        Parameters
        ----------
        keyword : str or unicode
            搜索文字
        page : int, optional
            页数 the default is 1
        timesn : WechatSogouConst.search_article_time
            时间 anytime 没有限制 / day 一天 / week 一周 / month 一月 / year 一年 / specific 自定
            the default is anytime
        article_type : WechatSogouConst.search_article_type
            含有内容的类型 image 有图 / video 有视频 / rich 有图和视频 / all 啥都有
        ft, et : datetime.date or None
            当 tsn 是 specific 时,ft 代表开始时间,如: 2017-07-01
            当 tsn 是 specific 时,et 代表结束时间,如: 2017-07-15
        unlock_callback : callable
            处理出现验证码页面的函数,参见 unlock_callback_example
        identify_image_callback : callable
            处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example
        decode_url : bool
            是否解析 url

        Returns
        -------
        list[dict]
            {
                'article': {
                    'title': '',  # 文章标题
                    'url': '',  # 文章链接
                    'imgs': '',  # 文章图片list
                    'abstract': '',  # 文章摘要
                    'time': ''  # 文章推送时间
                },
                'gzh': {
                    'profile_url': '',  # 公众号最近10条群发页链接
                    'headimage': '',  # 头像
                    'wechat_name': '',  # 名称
                    'isv': '',  # 是否加v
                }
            }

        Raises
        ------
        WechatSogouRequestsException
            requests error
        """
        def limit_sleep():
            """
            根据limit_seconds参数延迟一段时间
            """
            seconds = self.limit_seconds
            if seconds: time.sleep(seconds)
        url = WechatSogouRequest.gen_search_article_url(keyword, page, timesn, article_type, ft, et)
        session = requests.session()
        try:
            resp = self.__get_by_unlock(url, WechatSogouRequest.gen_search_article_url(keyword),
                                        unlock_platform=self.__unlock_sogou,
                                        unlock_callback=unlock_callback,
                                        identify_image_callback=identify_image_callback,
                                        session=session)

            article_list = WechatSogouStructuring.get_article_by_search(resp.text)

            limit_sleep()
            for i in article_list:
                if decode_url:
                    i['article']['url'] = self.__format_url(i['article']['url'], url, resp.text, unlock_callback=unlock_callback, identify_image_callback=identify_image_callback, session=session)
                    limit_sleep()
                    i['gzh']['profile_url'] = self.__format_url(i['gzh']['profile_url'], url, resp.text, unlock_callback=unlock_callback, identify_image_callback=identify_image_callback, session=session)
                yield i
        except WechatSogouRequestsException as e:
            raise e
Exemplo n.º 22
0
    def test_get_article_by_search(self):
        file_name = os.path.join(fake_data_path, 'search-gaokao-article.html')
        with io.open(file_name, encoding='utf-8') as f:
            search_gaokao_article = f.read()

        article_list = WechatSogouStructuring.get_article_by_search(search_gaokao_article)

        titles = []
        abstracts = []
        gzh_names = []
        isvs = []
        assert_equal(10, len(article_list))
        for i in article_list:
            article = i['article']
            titles.append(article['title'])
            abstracts.append(article['abstract'])

            assert_in('mp.weixin.qq.com/s?src=3&timestamp=', article['url'])
            assert_true(isinstance(article['imgs'], list))
            assert_greater_equal(len(article['imgs']), 1)

            gzh = i['gzh']

            assert_in('mp.weixin.qq.com/profile?src=3&timestamp', gzh['profile_url'])
            assert_in('wx.qlogo.cn/mmhead', gzh['headimage'])
            gzh_names.append(gzh['wechat_name'])
            isvs.append(gzh['isv'])

        # article
        assert_equal(['高考有多重要,为什么要重视高考?丨微观点',
                      '高考:穷人考不好,中产考状元,精英不高考',
                      '关于高考志愿的一点建议,仅供参考!',
                      '刚刚,高考“满分”诞生了!(附各省高考分数线)',
                      '高考学霸榜出炉!义乌最高分是她!排名...',
                      '【高考】权威发布!2017年我省高考各项日程',
                      '【高考】黑龙江省2017年普通高考成绩即将发布',
                      '高考2017 | 全国各省区市高考录取时间大汇总,最新最全!',
                      '高考志愿这么填,等于多考20分!这位特级教师的志愿填报方法很管用!',
                      '高考填志愿,如何选专业?学长学姐有话说'],
                     titles)
        assert_equal(['针对这个问题,其实占豪已经谈过,但还是想借高考之后、借这位小战友的留言,结合自己的人生经验,谈谈个人对这件事的看法....',
                      '#条条大路通罗马,有人就出生在罗马#前几天北京文科高考状元熊轩昂接受澎湃新闻的采访的时候,说了下面这段话. “农村地区的...',
                      '最近一直有哥迷留言问,填报高考志愿该选什么专业? 讲真,这个问题很难回答.专业选择没有绝对的好坏对错,跟考试成绩、个人兴...',
                      '高考会有满分的情况吗?还真有!6月22日开始,全国各省的高考成绩陆续发布.22日晚上,成都市青白江区一个小区内人声鼎沸,因...',
                      '浙江新高考各类别各段分数线及考生成绩于昨日揭晓.考生可凭考生号、密码查询自己的考试成绩!今年的高考成绩,经浙江省教育考...',
                      '根据我省招生录取工作安排,现将近期有关高考工作日程公布如下:一、高考成绩公布时间6月24日左右省招考院通过黑龙江省招生考...',
                      '黑龙江省2017年普通高考成绩即将发布 我省今年高考网上评卷工作现已结束,经过成绩核查、成绩校验等多个环节后,我省高考成绩...',
                      '2017年高考录取工作开始了,各省区市高考录取工作何时进行?为了方便考生和家长及时了解,小编为大家作了最新最全的梳理.(图...',
                      '各地高考成绩已陆续公布,在本公众号回复“高考查分”即可查询!~长按二维码即可关注本车~自昨天开始,全国各省份陆续公布...',
                      '导语高考成绩和批次线已经出来了,想必同学们已经开始进入另一重要环节——志愿填报.你是不是在为选专业而纠结痛苦?不怕!...'],
                     abstracts)

        # gzh
        assert_equal(['占豪',
                      '才华有限青年',
                      '新闻哥',
                      '光明网',
                      '义乌十八腔',
                      '龙招港',
                      '龙招港',
                      '微言教育',
                      '高考直通车',
                      '阳光高考信息平台', ],
                     gzh_names)
        assert_in(1, isvs)
        assert_in(0, isvs)
Exemplo n.º 23
0
    def test_get_article_by_history_json(self):
        file_name = os.path.join(fake_data_path, 'bitsea-history.html')
        with io.open(file_name, encoding='utf-8') as f:
            gzh_history = f.read()

        article_list = WechatSogouStructuring.get_article_by_history_json(
            gzh_history)
        titles = []
        urls = []
        digests = []
        for i in article_list:
            assert_equal('和菜头', i['author'])
            assert_equal('49', i['type'])
            assert_in('mp.weixin.qq.com/s?timestamp=', i['content_url'])
            assert_in(i['copyright_stat'], [11, 100])
            assert_in('mmbiz.qpic.cn/mmbiz_jpg/', i['cover'])
            assert_greater_equal(
                datetime.datetime.fromtimestamp(i['datetime']),
                datetime.datetime(2000, 1, 1))

            urls.append(i['content_url'])
            titles.append(i['title'])
            digests.append(i['abstract'])

        assert_equal([
            '帝都深处好修行',
            '如果我有个好一点的初中英文老师',
            '【广告】让手机清凉一哈',
            '写给各位陛下',
            '可能是年度电影的《大护法》',
            '怎样决定要不要去相信一个人',
            '照亮世界的那个人',
            '《冈仁波齐》观后',
            '没有什么火候不火候的',
            '完美受害人',
        ], titles)

        assert_equal([
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbILtKInZ4hqPp3-lC1nQZcN9Fd*BGbTQp7WlZyzLvCXy0Z8yFVF*lIDlo75pemv7kW8wov4Hz5-uiVzBT5q*Nwaw=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIPsfeXemAw1IR5Pt5J*6JqjpgotoKPL*6eVHbdcbi4JCEfsnhbnsQUTLQWpBZe5UILx8062e6A2L00LyjQArkxU=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIOVd*HwElAYiJum8Q6su3tILWksr-4u9WZPSrfT7A6nErJ3f0kW8V1Jv9evurTe5X4pQrjjCZcE6WeYGwDJIH0Q=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIBtaRJpx-JbQsm-5X*GWfaS-jBtKyhOmAxio5OIROqwV71OrvtaxYq1oZG-WM9apKbLGDPIBc0sCFUB4WBOagwk=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbID-eM8BIKq1ef1ajiKO1jz1k0E6xa1ROpt2Eo3Af6OHQGfYIq-WrfEsn3jLwps1V*TXmP6443wUYgrrStzJwKPc=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIJenG0s3GyCaMQIK18U3CHsWrrGwuL5Z0X*DSoztV49L-ZPrf39mbml1GBkZnX*gueDdUJBIHgvyFsaVCTePLrI=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIE2LQ5dJqrG018DC4M7E5RQ3D4V1p*eBszVaqr2saxG864LssINc8RKcASbkdSDEMiguB9xwuMcJXgGANUpBjtg=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbINN4P-L*qGaX0SopEwmBNGbOUc*Ad5D8TKEUZOPNduI4uupwRQFL*I4r151vpRYSA92EYzb34uf82WZJMa5-kTU=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIEhfSajMgMm4uzkdEhe*6MP8H9YKg1q38xqFlBV3*sJxgwupUV8b1Q2c6OhhBEZgCTyKQvHWnGLDLBH0gvC10zQ=',
            'http://mp.weixin.qq.com/s?timestamp=1500903767&src=3&ver=1&signature=X4l0IQ091w0DY2ERU7fD*h0VUwBxeHPOJH-Uk-vAfaPamMl6ij7fqAIHomnXQ2X2*2J94H0pixVjsjEkL0TbIBK5p9HtcN9dTEMbIU5Vspa3IaeGox55FYOfhNbWBL2Td4hxYt3GKGzRe-TlOPVlDWXuy8CvdD1ap1fmhNt9Cy0='
        ], urls)

        assert_equal([
            '善哉,善哉!',
            '说出来今天的人根本不会信,我的初中英文老师李女士在上课的时候打毛衣。',
            '奔走相告:过气网红接到新广告!请点击,请阅读,请留言!',
            '陛下们!微臣有话要说!',
            '对,我就那么说了,不服来咬我啊?',
            '在一个现代商业社会里,如何决定要不要去相信一个人?如何把人际关系判定的时间精力节省下来?网络慈父和菜头是这么说的:',
            '在一名凡夫身上,我看到了菩萨那样的行止。',
            '昨晚看了电影《冈仁波齐》,我不喜欢。',
            '如果你是厨艺初学者,忘掉火候,那不是你应该关心的事情。',
            '野鸡给自己加戏,观众不说话,并不等于看不明白。',
        ], digests)
Exemplo n.º 24
0
    def get_gzh_artilce_by_history(self, keyword=None, url=None,
                                   unlock_callback_sogou=None,
                                   identify_image_callback_sogou=None,
                                   unlock_callback_weixin=None,
                                   identify_image_callback_weixin=None):
        """从 公众号的最近10条群发页面 提取公众号信息 和 文章列表信息

        对于出现验证码的情况,可以由使用者自己提供:
            1、函数 unlock_callback ,这个函数 handle 出现验证码到解决的整个流程
            2、也可以 只提供函数 identify_image_callback,这个函数输入验证码二进制数据,输出验证码文字,剩下的由 wechatsogou 包来解决
        注意:
            函数 unlock_callback 和 identify_image_callback 只需要提供一个,如果都提供了,那么 identify_image_callback 不起作用

        Parameters
        ----------
        keyword : str or unicode
            公众号的id 或者name
        url : str or unicode
            群发页url,如果不提供url,就先去搜索一遍拿到url
        unlock_callback_sogou : callable
            处理出现 搜索 的时候出现验证码的函数,参见 unlock_callback_example
        identify_image_callback_sogou : callable
            处理 搜索 的时候处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example
        unlock_callback_weixin : callable
            处理出现 历史页 的时候出现验证码的函数,参见 unlock_callback_example
        identify_image_callback_weixin : callable
            处理 历史页 的时候处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example

        Returns
        -------
        dict
            {
                'gzh': {
                    'wechat_name': '',  # 名称
                    'wechat_id': '',  # 微信id
                    'introduction': '',  # 描述
                    'authentication': '',  # 认证
                    'headimage': ''  # 头像
                },
                'article': [
                    {
                        'send_id': '',  # 群发id,注意不唯一,因为同一次群发多个消息,而群发id一致
                        'datetime': '',  # 群发datatime
                        'type': '',  # 消息类型,均是49,表示图文
                        'main': 0,  # 是否是一次群发的第一次消息
                        'title': '',  # 文章标题
                        'abstract': '',  # 摘要
                        'fileid': '',  #
                        'content_url': '',  # 文章链接
                        'source_url': '',  # 阅读原文的链接
                        'cover': '',  # 封面图
                        'author': '',  # 作者
                        'copyright_stat': '',  # 文章类型,例如:原创啊
                    },
                    ...
                ]
            }


        Raises
        ------
        WechatSogouRequestsException
            requests error
        """
        if url is None:
            gzh_list = self.get_gzh_info(keyword, unlock_callback_sogou, identify_image_callback_sogou)
            if 'profile_url' not in gzh_list:
                raise Exception()  # todo use ws exception
            url = gzh_list['profile_url']

        resp = self.__get_by_unlock(url, WechatSogouRequest.gen_search_article_url(keyword),
                                    is_need_unlock=lambda x: '请输入验证码' in x.text,
                                    unlock_platform=self.__unlock_wechat,
                                    unlock_callback=unlock_callback_weixin,
                                    identify_image_callback=identify_image_callback_weixin)

        return WechatSogouStructuring.get_gzh_info_and_article_by_history(resp.text)
Exemplo n.º 25
0
    def search_article(self, keyword, page=1, timesn=WechatSogouConst.search_article_time.anytime,
                       article_type=WechatSogouConst.search_article_type.all, ft=None, et=None,
                       unlock_callback=None,
                       identify_image_callback=None):
        """搜索 文章

        对于出现验证码的情况,可以由使用者自己提供:
            1、函数 unlock_callback ,这个函数 handle 出现验证码到解决的整个流程
            2、也可以 只提供函数 identify_image_callback,这个函数输入验证码二进制数据,输出验证码文字,剩下的由 wechatsogou 包来解决
        注意:
            函数 unlock_callback 和 identify_image_callback 只需要提供一个,如果都提供了,那么 identify_image_callback 不起作用

        Parameters
        ----------
        keyword : str or unicode
            搜索文字
        page : int, optional
            页数 the default is 1
        timesn : WechatSogouConst.search_article_time
            时间 anytime 没有限制 / day 一天 / week 一周 / month 一月 / year 一年 / specific 自定
            the default is anytime
        article_type : WechatSogouConst.search_article_type
            含有内容的类型 image 有图 / video 有视频 / rich 有图和视频 / all 啥都有
        ft, et : datetime.date or None
            当 tsn 是 specific 时,ft 代表开始时间,如: 2017-07-01
            当 tsn 是 specific 时,et 代表结束时间,如: 2017-07-15
        unlock_callback : callable
            处理出现验证码页面的函数,参见 unlock_callback_example
        identify_image_callback : callable
            处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example

        Returns
        -------
        list[dict]
            {
                'article': {
                    'title': '',  # 文章标题
                    'url': '',  # 文章链接
                    'imgs': '',  # 文章图片list
                    'abstract': '',  # 文章摘要
                    'time': ''  # 文章推送时间
                },
                'gzh': {
                    'profile_url': '',  # 公众号最近10条群发页链接
                    'headimage': '',  # 头像
                    'wechat_name': '',  # 名称
                    'isv': '',  # 是否加v
                }
            }

        Raises
        ------
        WechatSogouRequestsException
            requests error
        """
        url = WechatSogouRequest.gen_search_article_url(keyword, page, timesn, article_type, ft, et)
        resp = self.__get_by_unlock(url, WechatSogouRequest.gen_search_article_url(keyword),
                                    is_need_unlock=lambda x: 'antispider' in x.url,
                                    unlock_platform=self.__unlock_sogou,
                                    unlock_callback=unlock_callback,
                                    identify_image_callback=identify_image_callback)

        return WechatSogouStructuring.get_article_by_search(resp.text)
Exemplo n.º 26
0
    def search_article(self,
                       keyword,
                       page=1,
                       timesn=0,
                       article_type=WechatSogouRequest.TYPE_ALL,
                       ft=None,
                       et=None,
                       deblocking_callback=None,
                       identify_image_callback=None):
        """搜索 文章

        对于出现验证码的情况,可以由使用者自己提供:
            1、函数 deblocking_callback ,这个函数 handle 出现验证码到解决的整个流程
            2、也可以 只提供函数 identify_image_callback,这个函数输入验证码二进制数据,输出验证码文字,剩下的由 wechatsogou 包来解决
        注意:
            函数 deblocking_callback 和 identify_image_callback 只需要提供一个,如果都提供了,那么 identify_image_callback 不起作用

        Parameters
        ----------
        keyword : str or unicode
            搜索文字
        page : int, optional
            页数 the default is 1
        timesn : {0, 1, 2, 3, 4, 5}
            时间 0 没有限制 / 1一天 / 2一周 / 3一月 / 4一年 / 5自定
            the default is 0
        article_type : {'image', 'video', 'rich', 'all'}
            含有内容的类型 TYPE_IMAGE 有图 / TYPE_VIDEO 有视频 / TYPE_RICH 有图和视频 / TYPE_ALL 啥都有
        ft, et : datetime.date or None
            当 tsn 是 5 时,ft 代表开始时间,如: 2017-07-01
            当 tsn 是 5 时,et 代表结束时间,如: 2017-07-15
        deblocking_callback : callable
            处理出现验证码页面的函数,参见 deblocking_callback_example
        identify_image_callback : callable
            处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example

        Returns
        -------
        list[dict]
            {
                'url': '',
                'img': '',
                'name': '',
                'wechat_id': '',
                'post_perm': '',
                'qrcode': '',
                'introduction': '',
                'authentication': ''
            }

        Raises
        ------
        WechatSogouRequestsException
            requests error
        """
        req = requests.session()

        url = WechatSogouRequest.gen_search_article_url(
            keyword,
            page,
            timesn=timesn,
            article_type=article_type,
            ft=ft,
            et=et)
        url_referer = WechatSogouRequest.gen_search_article_url(keyword)

        resp = WechatSogouRequest.get(
            url, req=req, headers=self.__set_cookie(referer=url_referer))

        if not resp.ok:
            raise WechatSogouRequestsException('WechatSogouAPI search_article',
                                               resp)

        if 'antispider' in resp.url:
            self.__deblocking_search(url, resp, req, deblocking_callback,
                                     identify_image_callback)
            resp = WechatSogouRequest.get(
                url, req=req,
                headers=self.__set_cookie(referer=url_referer))  # req=req

        return WechatSogouStructuring.get_article_by_search(resp.text)
Exemplo n.º 27
0
    def get_gzh_artilce_by_history(self,
                                   keyword=None,
                                   url=None,
                                   unlock_callback_sogou=None,
                                   identify_image_callback_sogou=None,
                                   unlock_callback_weixin=None,
                                   identify_image_callback_weixin=None):
        """从 公众号的最近10条群发页面 提取公众号信息 和 文章列表信息

        对于出现验证码的情况,可以由使用者自己提供:
            1、函数 unlock_callback ,这个函数 handle 出现验证码到解决的整个流程
            2、也可以 只提供函数 identify_image_callback,这个函数输入验证码二进制数据,输出验证码文字,剩下的由 wechatsogou 包来解决
        注意:
            函数 unlock_callback 和 identify_image_callback 只需要提供一个,如果都提供了,那么 identify_image_callback 不起作用

        Parameters
        ----------
        keyword : str or unicode
            公众号的id 或者name
        url : str or unicode
            群发页url,如果不提供url,就先去搜索一遍拿到url
        unlock_callback_sogou : callable
            处理出现 搜索 的时候出现验证码的函数,参见 unlock_callback_example
        identify_image_callback_sogou : callable
            处理 搜索 的时候处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example
        unlock_callback_weixin : callable
            处理出现 历史页 的时候出现验证码的函数,参见 unlock_callback_example
        identify_image_callback_weixin : callable
            处理 历史页 的时候处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example

        Returns
        -------
        dict
            {
                'gzh': {
                    'wechat_name': '',  # 名称
                    'wechat_id': '',  # 微信id
                    'introduction': '',  # 描述
                    'authentication': '',  # 认证
                    'headimage': ''  # 头像
                },
                'article': [
                    {
                        'send_id': '',  # 群发id,注意不唯一,因为同一次群发多个消息,而群发id一致
                        'datetime': '',  # 群发datatime
                        'type': '',  # 消息类型,均是49,表示图文
                        'main': 0,  # 是否是一次群发的第一次消息
                        'title': '',  # 文章标题
                        'abstract': '',  # 摘要
                        'fileid': '',  #
                        'content_url': '',  # 文章链接
                        'source_url': '',  # 阅读原文的链接
                        'cover': '',  # 封面图
                        'author': '',  # 作者
                        'copyright_stat': '',  # 文章类型,例如:原创啊
                    },
                    ...
                ]
            }


        Raises
        ------
        WechatSogouRequestsException
            requests error
        """
        if url is None:
            gzh_list = self.get_gzh_info(keyword, unlock_callback_sogou,
                                         identify_image_callback_sogou)
            if 'profile_url' not in gzh_list:
                raise Exception()  # todo use ws exception
            url = gzh_list['profile_url']

        resp = self.__get_by_unlock(
            url,
            WechatSogouRequest.gen_search_article_url(keyword),
            is_need_unlock=lambda x: '请输入验证码' in x.text,
            unlock_platform=self.__unlock_wechat,
            unlock_callback=unlock_callback_weixin,
            identify_image_callback=identify_image_callback_weixin)

        return WechatSogouStructuring.get_gzh_info_and_article_by_history(
            resp.text)
Exemplo n.º 28
0
    def test_get_gzh_artilce_by_hot(self):
        file_name = os.path.join(fake_data_path,
                                 'wapindex-wap-0612-wap_8-0.html')
        with io.open(file_name, encoding='utf-8') as f:
            gzh_artilce_by_hot = f.read()

            gzh_artilces = WechatSogouStructuring.get_gzh_artilce_by_hot(
                gzh_artilce_by_hot)

        for gzh_artilce in gzh_artilces:
            assert_in('gzh', gzh_artilce)
            assert_in('article', gzh_artilce)
            assert_in('http://mp.weixin.qq.com/s?src=',
                      gzh_artilce['article']['url'])
        assert_greater_equal(len(gzh_artilces), 10)

        wechat_names = []
        headimages = []
        titles = []
        times = []
        for i in gzh_artilces:
            wechat_names.append(i['gzh']['wechat_name'])
            headimages.append(i['gzh']['headimage'])
            titles.append(i['article']['title'])
            times.append(i['article']['time'])

        assert_equal([
            '全球汽车精选', '车早茶', '吴佩频道', '驾考宝典', '腾讯汽车', '新车评', '非常好车', '汽车情报所',
            '一猫汽车资讯', '资深科技控', '郎club', '科技日报', '汽车使用宝典', '名车报', '科普中国网'
        ], wechat_names)
        assert_equal([
            'http://img03.sogoucdn.com/app/a/100520090/oIWsFt1dGMefD1f8dOg2UCwQUjKs',
            'http://img04.sogoucdn.com/app/a/100520090/oIWsFtwoQX8wX7w6loDevPqLEC_I',
            'http://img03.sogoucdn.com/app/a/100520090/oIWsFt9Hbbtr9VLnfR9i_K5Z8D48',
            'http://img04.sogoucdn.com/app/a/100520090/oIWsFt3txmWu-usvUa6gU0qlyEVo',
            'http://img01.sogoucdn.com/app/a/100520090/oIWsFt8VDujUqNSCfruXtMNfekaw',
            'http://img01.sogoucdn.com/app/a/100520090/oIWsFt9YD5HWLDe5QAkuvh0JWrgw',
            'http://img01.sogoucdn.com/app/a/100520090/oIWsFt_WUnpQ7lZajAstgL8o1lWo',
            'http://img02.sogoucdn.com/app/a/100520090/oIWsFtzUnzWUMz1PMek5zjVlS42U',
            'http://img03.sogoucdn.com/app/a/100520090/oIWsFt2yk491dhhSP940JzLEameY',
            'http://img03.sogoucdn.com/app/a/100520090/oIWsFtzm9UtmgY-SkOTFwQFpGsU8',
            'http://img02.sogoucdn.com/app/a/100520090/oIWsFt7VwiM8GqYcv8DBNb-k5NBQ',
            'http://img03.sogoucdn.com/app/a/100520090/oIWsFt2tjckivF8b0MP_nNTdESkE',
            'http://img01.sogoucdn.com/app/a/100520090/oIWsFtzC2r61_riTCWp5iHX04fmo',
            'http://img02.sogoucdn.com/app/a/100520090/oIWsFt8JIY_-o7DBMxorP19hcF0Q',
            'http://img04.sogoucdn.com/app/a/100520090/oIWsFtyV5sdIXU2uy4m6oVBq77nA'
        ], headimages)
        assert_equal([
            '不做这个动作,你的轮胎3个月就要换!', '新车质量最差的十个品牌?国人表示难以接受……',
            '带着米其林的指引去看古德伍德|品牌', '方向盘打法巧记口诀,科目二提分就靠它了!',
            '宝马“鸡腿”、奥迪“游艇”,这些奇葩的挡杆你见过几个?', '你没看错,我们做了期途昂和途锐的对比',
            '7成特斯拉被召回,难道是质量不过关?', '在中国惹不起的7种车,遇到请回避!',
            '迈腾摊上大事儿了 全新一代君威17.58万起', '面对这份驾享,朝廷大人都忍不住亲自上阵!',
            '外卖小哥被暴晒:底层人士的悲哀,有钱人不会懂', '自动驾驶还处于“新手”阶段,何时成为“老司机”?院士这样说……',
            '高速上碰到石头,是躲还是撞?', '装什么神秘,不就是加长版的讴歌TLX吗!', '一个动作,车里的人集体中毒!很多人都忽略了'
        ], titles)
        assert_equal([
            1501328135, 1501327941, 1501326826, 1501326716, 1501326675,
            1501326455, 1501326222, 1501325595, 1501325529, 1501325521,
            1501325223, 1501324531, 1501324443, 1501324310, 1501323274
        ], times)
Exemplo n.º 29
0
    def search_article(self,
                       keyword,
                       page=1,
                       timesn=WechatSogouConst.search_article_time.anytime,
                       article_type=WechatSogouConst.search_article_type.all,
                       ft=None,
                       et=None,
                       unlock_callback=None,
                       identify_image_callback=None):
        """搜索 文章

        对于出现验证码的情况,可以由使用者自己提供:
            1、函数 unlock_callback ,这个函数 handle 出现验证码到解决的整个流程
            2、也可以 只提供函数 identify_image_callback,这个函数输入验证码二进制数据,输出验证码文字,剩下的由 wechatsogou 包来解决
        注意:
            函数 unlock_callback 和 identify_image_callback 只需要提供一个,如果都提供了,那么 identify_image_callback 不起作用

        Parameters
        ----------
        keyword : str or unicode
            搜索文字
        page : int, optional
            页数 the default is 1
        timesn : WechatSogouConst.search_article_time
            时间 anytime 没有限制 / day 一天 / week 一周 / month 一月 / year 一年 / specific 自定
            the default is anytime
        article_type : WechatSogouConst.search_article_type
            含有内容的类型 image 有图 / video 有视频 / rich 有图和视频 / all 啥都有
        ft, et : datetime.date or None
            当 tsn 是 specific 时,ft 代表开始时间,如: 2017-07-01
            当 tsn 是 specific 时,et 代表结束时间,如: 2017-07-15
        unlock_callback : callable
            处理出现验证码页面的函数,参见 unlock_callback_example
        identify_image_callback : callable
            处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example

        Returns
        -------
        list[dict]
            {
                'article': {
                    'title': '',  # 文章标题
                    'url': '',  # 文章链接
                    'imgs': '',  # 文章图片list
                    'abstract': '',  # 文章摘要
                    'time': ''  # 文章推送时间
                },
                'gzh': {
                    'profile_url': '',  # 公众号最近10条群发页链接
                    'headimage': '',  # 头像
                    'wechat_name': '',  # 名称
                    'isv': '',  # 是否加v
                }
            }

        Raises
        ------
        WechatSogouRequestsException
            requests error
        """
        url = WechatSogouRequest.gen_search_article_url(
            keyword, page, timesn, article_type, ft, et)
        resp = self.__get_by_unlock(
            url,
            WechatSogouRequest.gen_search_article_url(keyword),
            is_need_unlock=lambda x: 'antispider' in x.url,
            unlock_platform=self.__unlock_sogou,
            unlock_callback=unlock_callback,
            identify_image_callback=identify_image_callback)

        return WechatSogouStructuring.get_article_by_search(resp.text)
Exemplo n.º 30
0
    def test_get_article_by_search(self):
        file_name = os.path.join(fake_data_path, 'search-gaokao-article.html')
        with io.open(file_name, encoding='utf-8') as f:
            search_gaokao_article = f.read()

        article_list = WechatSogouStructuring.get_article_by_search(
            search_gaokao_article)

        titles = []
        abstracts = []
        gzh_names = []
        isvs = []
        assert_equal(10, len(article_list))
        for i in article_list:
            article = i['article']
            titles.append(article['title'])
            abstracts.append(article['abstract'])

            assert_in('mp.weixin.qq.com/s?src=3&timestamp=', article['url'])
            assert_true(isinstance(article['imgs'], list))
            assert_greater_equal(len(article['imgs']), 1)

            gzh = i['gzh']

            assert_in('mp.weixin.qq.com/profile?src=3&timestamp',
                      gzh['profile_url'])
            assert_in('wx.qlogo.cn/mmhead', gzh['headimage'])
            gzh_names.append(gzh['wechat_name'])
            isvs.append(gzh['isv'])

        # article
        assert_equal([
            '高考有多重要,为什么要重视高考?丨微观点', '高考:穷人考不好,中产考状元,精英不高考',
            '关于高考志愿的一点建议,仅供参考!', '刚刚,高考“满分”诞生了!(附各省高考分数线)',
            '高考学霸榜出炉!义乌最高分是她!排名...', '【高考】权威发布!2017年我省高考各项日程',
            '【高考】黑龙江省2017年普通高考成绩即将发布', '高考2017 | 全国各省区市高考录取时间大汇总,最新最全!',
            '高考志愿这么填,等于多考20分!这位特级教师的志愿填报方法很管用!', '高考填志愿,如何选专业?学长学姐有话说'
        ], titles)
        assert_equal([
            '针对这个问题,其实占豪已经谈过,但还是想借高考之后、借这位小战友的留言,结合自己的人生经验,谈谈个人对这件事的看法....',
            '#条条大路通罗马,有人就出生在罗马#前几天北京文科高考状元熊轩昂接受澎湃新闻的采访的时候,说了下面这段话. “农村地区的...',
            '最近一直有哥迷留言问,填报高考志愿该选什么专业? 讲真,这个问题很难回答.专业选择没有绝对的好坏对错,跟考试成绩、个人兴...',
            '高考会有满分的情况吗?还真有!6月22日开始,全国各省的高考成绩陆续发布.22日晚上,成都市青白江区一个小区内人声鼎沸,因...',
            '浙江新高考各类别各段分数线及考生成绩于昨日揭晓.考生可凭考生号、密码查询自己的考试成绩!今年的高考成绩,经浙江省教育考...',
            '根据我省招生录取工作安排,现将近期有关高考工作日程公布如下:一、高考成绩公布时间6月24日左右省招考院通过黑龙江省招生考...',
            '黑龙江省2017年普通高考成绩即将发布 我省今年高考网上评卷工作现已结束,经过成绩核查、成绩校验等多个环节后,我省高考成绩...',
            '2017年高考录取工作开始了,各省区市高考录取工作何时进行?为了方便考生和家长及时了解,小编为大家作了最新最全的梳理.(图...',
            '各地高考成绩已陆续公布,在本公众号回复“高考查分”即可查询!~长按二维码即可关注本车~自昨天开始,全国各省份陆续公布...',
            '导语高考成绩和批次线已经出来了,想必同学们已经开始进入另一重要环节——志愿填报.你是不是在为选专业而纠结痛苦?不怕!...'
        ], abstracts)

        # gzh
        assert_equal([
            '占豪',
            '才华有限青年',
            '新闻哥',
            '光明网',
            '义乌十八腔',
            '龙招港',
            '龙招港',
            '微言教育',
            '高考直通车',
            '阳光高考信息平台',
        ], gzh_names)
        assert_in(1, isvs)
        assert_in(0, isvs)
Exemplo n.º 31
0
# -*- coding: utf-8 -*-

from __future__ import absolute_import, unicode_literals, print_function

import os

from wechatsogou.request import WechatSogouRequest
from wechatsogou.structuring import WechatSogouStructuring

ws = WechatSogouRequest()
ws_structuring = WechatSogouStructuring()

empty_search_result_keyword = 'gggggggggggggggggg'
gaokao_keyword = '高考'
fake_data_path = '{}/file'.format(
    os.getcwd() if 'test' in os.getcwd() else '{}/test'.format(os.getcwd()))
Exemplo n.º 32
0
    def search_gzh(self,
                   keyword,
                   page=1,
                   deblocking_callback=None,
                   identify_image_callback=None):
        """搜索 公众号

        对于出现验证码的情况,可以由使用者自己提供:
            1、函数 deblocking_callback ,这个函数 handle 出现验证码到解决的整个流程
            2、也可以 只提供函数 identify_image_callback,这个函数输入验证码二进制数据,输出验证码文字,剩下的由 wechatsogou 包来解决
        注意:
            函数 deblocking_callback 和 identify_image_callback 只需要提供一个,如果都提供了,那么 identify_image_callback 不起作用

        Parameters
        ----------
        keyword : str or unicode
            搜索文字
        page : int, optional
            页数 the default is 1
        deblocking_callback : callable
            处理出现验证码页面的函数,参见 deblocking_callback_example
        identify_image_callback : callable
            处理验证码函数,输入验证码二进制数据,输出文字,参见 identify_image_callback_example

        Returns
        -------
        list[dict]
            {
                'url': '',
                'img': '',
                'name': '',
                'wechat_id': '',
                'post_perm': '',
                'qrcode': '',
                'introduction': '',
                'authentication': ''
            }

        Raises
        ------
        WechatSogouRequestsException
            requests error
        """
        req = requests.session()

        url = WechatSogouRequest.gen_search_gzh_url(keyword, page)
        resp = WechatSogouRequest.get(url,
                                      req=req,
                                      headers=self.__set_cookie())

        if not resp.ok:
            raise WechatSogouRequestsException('WechatSogouAPI search_gzh',
                                               resp)

        if 'antispider' in resp.url:
            self.__deblocking_search(url, resp, req, deblocking_callback,
                                     identify_image_callback)
            resp = WechatSogouRequest.get(
                url, req=req, headers=self.__set_cookie())  # req=req

        return WechatSogouStructuring.get_gzh_by_search(resp.text)