使用redis所维护的代理池抓取微信文章

搜狗搜索可以直接搜索微信文章,本次就是利用搜狗搜搜出微信文章,获得详细的文章url来得到文章的信息.并把我们感兴趣的内容存入到mongodb中。

因为搜狗搜索微信文章的反爬虫比较强,经常封IP,所以要在封了IP之后切换IP,这里用到github上的一个开源类,当运行这个类时,就会动态的在redis中维护一个ip池,并通过flask映射到网页中,可以通过访问 localhost:5000/get/

来获取IP

这是搜狗微信搜索的页面,

构造搜索url .搜索时会传递的参数,通过firefox浏览器可以查到:

代码如下,

from urllib.parse import urlencode
import requests
from settings import *
from requests.exceptions import ConnectionError
from pyquery import PyQuery as pq
import pymongo
from lxml.etree import XMLSyntaxError

class WeixinArticle(object):
    """
    通过搜狗搜索微信文章,爬取到文章的详细内容,并把我们感兴趣的内容存入到mongodb中
    因为搜狗搜索微信文章的反爬虫比较强,经常封IP,所以要在封了IP之后切换IP,这里用到github上的一个开源类,
    当运行这个类时,就会动态的redis中维护一个ip池,并通过flask映射到网页中,可以通过访问 localhost:5000/get/
    来获取IP,
    """
    # 定义一个全局变量,这样在各个函数中均可以使用,就不用在传递这个变量
    proxy = None

    def __init__(self):
        self.keyword = KEYWORD
        self.proxy_pool_url = PROXY_POOL_URL
        self.max_count = MAX_COUNT
        self.mongo_url = MONGO_URL
        self.mongo_db = MONGO_DB
        self.base_url = BASE_URL
        self.headers = HEADERS
        self.client = pymongo.MongoClient(self.mongo_url)
        self.db = self.client[self.mongo_db]

    def get_proxy(url):
        """获取我们所维护的IP"""
        try:
            response = requests.get(url)
            if response.status_code == 200:
                return response.text
            return None
        except ConnectionError:
            return self.get_proxy(url)

    def get_html(url, count=1):
        """
        通过传的url 获取搜狗微信文章页面信息,
        :param count: 表示最后递归的次数
        :return: 页面的信息
        """
        if not url:
            return None
        if count >= self.max_count:
            print("try many count ")
            return None
        print(‘crowling url ‘, url)
        print(‘crowling count ‘, count)
        # 定义一个全局变量,这样在各个函数中均可以使用,就不用在传递这个变量
        global proxy
        try:
            if proxy:
                # 如果有代理就用代理去访问
                proxy = {
                    "http": "http://" + proxy,
                }
                response = requests.get(url=url, allow_redirects=False, headers=self.headers, proxy=proxy)
            else:
                # 如果没有代理就不用代理去访问
                response = requests.get(url=url, allow_redirects=False, headers=self.headers)
            if response.status_code == 200:
                return response.text
            elif response.status_code == 302:
                # 如果重定向了,说明我们的IP被ban了,此时就要更换代理
                print("status code is 302 ")
                proxy = self.get_proxy(self.proxy_pool_url)
                if proxy:
                    print("Useing proxy: ", proxy)
                    return self.get_html(url)
                else:
                    # 如果我们的代理都获取失败,那这次爬取就完全失败了,此时返回None
                    print("Get proxy failed")
                    return None
            else:
                print("Occur Error : ", response.status_code)
        except ConnectionError as e:
            #我们只是递归调用max_count 这么多次,防止无限递归
            print("Error Occured ", e.args)
            count += 1
            proxy = self.get_proxy(self.proxy_pool_url)
            return self.get_html(url, count)

    def get_index(keyword, page):
        """use urlencode to constract url"""
        data = {
            "query": keyword,
            "type": 2,
            # "s_from": "input",
            # "ie": "utf8",
            "page": page
        }
        queries = urlencode(data)
        url = self.base_url + queries
        # 为了让程序的的流程更直观,可以不在这里调用 get_html函数,在main函数中调用
        # print(url)
        # html = get_html(url)
        # return html
        return url

    def parse_index_html(html):
        """解析get_html函数得到的html,即是通过关键字搜索的搜狗页面,解析这个页面得到微信文章的url"""
        if not html:
            """如果传进来的html是None,则直接返回"""
            print("the html is None")
            return None
        doc = pq(html)
        items = doc(".news-list li .txt-box h3 a").items()
        for item in items:
            article_url = item.attr("href")
            yield article_url

    def get_detail(url):
        """通过parse_index函数得到微信文章的url,利用requests去得到这个url的网页信息"""
        try:
            response = requests.get(url)
            if response.status_code == 200:
                return response.text
            return None
        except ConnectionError:
            return None

    def parse_detail(html):
        """解析通过get_detail函数得到微信文章url网页信息,得到我们想要的信息"""
        if not html:
            return None
        try:
            doc = pq(html)
            title = doc(‘#activity-name‘).text()
            content = doc(".rich_media_content p span").text()
            date = doc("#post-date").text()
            weichat_name = doc("#post-user").text()
            return {
                "title": title,
                "content": content,
                "date": date,
                "weichat_name": weichat_name,
            }
        except XMLSyntaxError:
            return None

    def save_to_mongo(data):
        """保存到mongodb 中,这里我们希望 title 不重复,所以用update 这种方式进行更新"""
        if self.db[‘articls‘].update({"title": data["title"]}, {"$set": data}, True):
            print("save to mongo ")
        else:
            print("save to mongo failed ", data["title"])

    def main():
        """
        爬虫的主要逻辑就在main函数中,
        在所有的处理函数中都加了异常处理,和当传入的值是None时的处理,所以在main函数就不用再做处理
        """

        keyword = self.keyword
        for page in range(1, 5):
            url = self.get_index(keyword, page)
            html = self.get_html(url)
            article_url = self.parse_index_html(html)
            article_html = self.get_detail(article_url)
            article_data = self.parse_detail(article_html)
            self.save_to_mongo(article_data)

    def run(self):
        self.main()

if __name__ == "__main__":
    weixin_article = WeixinArticle()
   weixin_article.run()

之后,把这们常用的配置写在settings.py,方便程序的修改。

KEYWORD="python"
PROXY_POOL_URL="http://127.0.0.1:5000"
MAX_COUNT=5
MONGO_URL="localhost"
MONGO_DB="weixin"
BASE_URL = "http://weixin.sogou.com/weixin?"
HEADERS = {
    # "Accept": "* / *",
    # "Accept-Encoding": "gzip, deflate",
    # "Accept-Language": "zh-CN,zh;q=0.9",
    # "Connection": "keep-alive",
    "Cookie": "SUID=2FF0747C4990A000000005A45FE0C; SUID=59A4FF3C52110A000000005A45FE0D; weixinIndexVisited=1; SUV=00E75AA0AF9B99675A45FE104A7DA232; CXID=B3DDF3C9EA20CECCB4F94A077C74ED; [email protected]@@@@@@@@@@; ABTEST=0|1517209704|v1; SNUID=D8A7384B3C395FD9D44BC22C3DDE2172; JSESSIONID=aaa3zBm9sI7SGeZhCaCew; ppinf=5|1517210191|1518419791|dHJ1c3Q6MToxfGNsaWVudGlkOjQ6MjAxN3x1bmlxbmFtZToxODolRTYlODElODElRTYlODAlODJ8Y3J0OjEwOjE1MTcyMTAxOTF8cmVmbmljazoxODolRTYlODElODElRTYlODAlODJ8dXNlcmlkOjQ0Om85dDJsdUN1Rm5aVTlaNWYzMGpjNVRDUGN6NW9Ad2VpeGluLnNvaHUuY29tfA; pprdig=m",
    "Host": "account.sogou.com",
    "Referer": "http://weixin.sogou.com/weixin?query=python&s_from=input&type=2&page=10&ie=utf8",
    "Upgrade-Insecure-Requests": "1",
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/63.0.3239.132 Safari/537.36"
}

项目目录结构如下:

关于怎么使用redis 维护一个代理池,见

原文地址:https://www.cnblogs.com/liuqianli/p/8379330.html

时间: 2024-07-30 07:02:32

使用redis所维护的代理池抓取微信文章的相关文章

使用redis+flask维护动态代理池

在进行网络爬虫时,会经常有封ip的现象.可以使用代理池来进行代理ip的处理. 代理池的要求:多站抓取,异步检测.定时筛选,持续更新.提供接口,易于提取. 代理池架构:获取器,过滤器,代理队列,定时检测. 使用https://github.com/Germey/ProxyPool/tree/master/proxypool代码进行分析. run.py里面的代码 from proxypool.api import app from proxypool.schedule import Schedule

[Python爬虫] 之十五:Selenium +phantomjs根据微信公众号抓取微信文章

借助搜索微信搜索引擎进行抓取 抓取过程 1.首先在搜狗的微信搜索页面测试一下,这样能够让我们的思路更加清晰 在搜索引擎上使用微信公众号英文名进行“搜公众号”操作(因为公众号英文名是公众号唯一的,而中文名可能会有重复,同时公众号名字一定要完全正确,不然可能搜到很多东西,这样我们可以减少数据的筛选工作, 只要找到这个唯一英文名对应的那条数据即可),即发送请求到'http://weixin.sogou.com/weixin?type=1&query=%s&ie=utf8&_sug_=n&

用代理抓取微信文章

GitHub:https://github.com/LXL-YAN/weixinArticles 原文地址:https://www.cnblogs.com/LXL616/p/10759571.html

asp.net MVC 抓取微信文章数据(正文)

1.抓微信的正文主要是调用第三方的接口(https://market.aliyun.com/products/56928004/cmapi012134.html) using Newtonsoft.Json; using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Net.Security; using System.Sec

根据微信号来抓取微信文章

<script type="text/javascript"> //计算字符串长度 String.prototype.strLen = function() { var len = 0; for (var i = 0; i < this.length; i++) { if (this.charCodeAt(i) > 255 || this.charCodeAt(i) < 0) len += 2; else len ++; } return len; } /

asp.net mvc抓取微信文章里面所有的图片

/// <summary> /// 下载指定URL下的所有图片 /// </summary> public class WebPageImage { /// <summary> /// 获取网页中全部图片 /// </summary> /// <param name="url">网页地址</param> /// <param name="charSet">网页编码,为空自动判断<

使用burpsuite等代理工具抓取docker容器中的数据包

使用burpsuite等代理工具抓取docker容器中的数据包,下面是详细的教程. 以docker中的某个漏洞平台(bwapp)为例,展示如何抓包. 1.首先使用docker下载bwapp: # docker pull raesene/bwapp 2.然后运行bwapp (使用命令   --env HTTP_PROXY="http://192.168.43.14:8080"   来进行代理设置,这里设置的是burpsuite中的ip地址以及端口) # docker run -d --n

Python 抓取微信公众号账号信息

搜狗微信搜索提供两种类型的关键词搜索,一种是搜索公众号文章内容,另一种是直接搜索微信公众号.通过微信公众号搜索可以获取公众号的基本信息及最近发布的10条文章,今天来抓取一下微信公众号的账号信息( 爬虫 首先通过首页进入,可以按照类别抓取,通过"查看更多"可以找出页面链接规则: import requests as req import re reTypes = r'id="pc_\d*" uigs="(pc_\d*)">([\s\S]*?)

基于Node.js的强大爬虫 能直接发布抓取的文章哦

基于Node.js的强大爬虫 能直接发布抓取的文章哦 基于Node.js的强大爬虫能直接发布抓取的文章哦!本爬虫源码基于WTFPL协议,感兴趣的小伙伴们可以参考一下 一.环境配置 1)搞一台服务器,什么linux都行,我用的是CentOS 6.5: 2)装个mysql数据库,5.5或5.6均可,图省事可以直接用lnmp或lamp来装,回头还能直接在浏览器看日志: 3)先安个node.js环境,我用的是0.12.7,更靠后的版本没试过: 4)执行npm -g install forever,安装f