爬虫笔记:通过使用代理池来解决部分反爬虫问题的方法

对《Python3网络爬虫开发实战》部分内容的总结。

1.所遇到的问题

以搜狗搜索引擎中中朋友圈的搜索为例,我们首先要登陆微信才可以看到全部的搜索内容。首先搜索apple,我们可以得到33612条结果。
在这里插入图片描述
之后打开开发者工具,并模拟爬虫在短时间疯狂换页,就会发现搜狗在此处的反爬虫手段。如果你在短时间大量访问,搜狗会甄别你为爬虫程序,并跳转到验证码页,如下:
在这里插入图片描述
这时我们在all中检索“weixin"我们就会发现,有一个网页的状态码为”302“,该状态码就意味着该网页向反爬虫页面的跳转。这就证明着我们访问的IP被封,需要输入验证码。在这里我们采取的一种解决方案就是利用代理池来更换访问IP,解决302的问题。
在这里插入图片描述

2.代理池的下载

2.1 github: [link](https://github.com/germey/proxypool)

使用该代理池同时需要安装“redis”数据库

pip install redis

安装好之后将Redis服务开启,确保有redis的进程(否则会出现”目标计算机拒绝“等错误)

2.2 配置代理池

cd proxypool

进入proxypool目录,修改settings.py文件

密码为Redis的密码,如果为空,则设置为无

2.3 安装依赖

pip3 install -r requirements.txt

2.4 打开代理池和API

python3 run.py

2.5 运行成功之后会出现如下

在这里插入图片描述

2.6 该代理池的大概的运行原理如下(图片源于崔庆才爬虫课程的截图)

在这里插入图片描述
大概就是从一些免费提供代理的网站爬取代理,然后进行测试过滤掉那些不能用的代理,将能用的代理放入代理队列,通过定时检测器,定时剔除不能使用的代理,并且提供一个接口方便我们提取。

2.7 获取代理 利用请求获取方法如下(参考上文安装代理池的github)

import requests

PROXY_POOL_URL = 'http://localhost:5000/get'

def get_proxy():
    try:
        response = requests.get(PROXY_POOL_URL)
        if response.status_code == 200:
            return response.text
    except ConnectionError:
        return None

3.使用代理处理反爬虫的代码实现。

3.1 代码思路

Created with Raphaël 2.2.0 抓取索引页的内容 分析HTML 判断状态码是否为302 ? 成功 使用代理池 yes no

3.2 代码开始引用及全局变量的定义。

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

base_url = 'http://weixin.sogou.com/weixin?'

headers = {//保证微信的登录状态 cookie已改动
    'Cookie': 'CXID=A4BD3E147F0C8B0D3DD3EFA6EB6B65; SUID=4C9EFA714B238B0A5C282BFE00008353; IPLOC=CN5000; SUV=1552135849980789; ABTEST=0|1552135851|v1; weixinIndexVisited=1; JSESSIONID=aaaE641h2DieVfUtjMZKw; ppinf=5|1552136293|1553345893|dHJ1c3Q6MToxfGNsaWVudGlkOjQ6MjAxN3x1bmlxbmFtZTo3OlJ5YW5fRnV8Y3J0OjEwOjE1NTIxMzYyOTN8cmVmbmljazo3OlJ5YW5fRnV8dXNlcmlkOjQ0Om85dDJsdUZ1RVQ1WDVFdVhGcmZTNnFtNkRHbzBAd2VpeGluLnNvaHUuY29tfA; pprdig=q3ucU1B68gQEBfdqqoc3dWGMtoA6O25mTWENqO4uMs26vUOFXAseB_wFyrerRqU8UANLsLMaqVX1WuOelu7BOWXfElCk4nB02f5NhdQtfm88fAx8Y_vh-STy8dbFTM4voQCEsXrHlR2xG6jv8lOSLIZ8dgheQyTLRh95f-znWEU; sgid=31-39599813-AVyDuGVQJbWdtOOAREDcD4I; PHPSESSID=u55o9jkcrg82lj24ing7hjrb45; sct=9; ppmdig=1552139618000000531d81ae50b5fd630d4b334893ff1096; SNUID=9F4227ACDCD85F77EB5E2F41DDA875A7',
    'Host': 'weixin.sogou.com',
    'Upgrade-Insecure-Requests': '1',
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3724.8 Safari/537.36'
    }

keyword = 'apple'

proxy_pool_url = 'http://127.0.0.1:5000/get' //代理所对应的接口

proxy = None //一开始将代理设为空,不使用代理,用电脑本机爬取 ,出现错误后替换代理。

max_count = 5

3.3 页面访问部分(get_index)。

def get_index(keyword,page): #传入两个参数
    data = {
        'query':keyword,
        'type' :2,
        'page': page
    }
    queries = urlencode(data) #用urlencode的方法将它转变为get请求参数
    url = base_url + queries  #拼接url
    html = get_html(url)
    return html

首先分析一下目标页面的get请求参数

https://weixin.sogou.com/weixin?type=2&query=apple&ie=utf8&s_from=input&_sug_=n&_sug_type_=1&w=01015002&oq=&ri=4&sourceid=sugg&sut=0&sst0=1552156860228&lkt=0%2C0%2C0&p=40040108

这个url的参数很多都可以省略,这里我们只留下query(搜索的内容),type(这里type=2证明它传递的是文章),page(页数)

https://weixin.sogou.com/weixin?query=apple&type=2&page=1

之后就是写一个字典,然后通过urlencode的方法将它转变为get请求参数,然后拼接url ,传递给get_html函数去判断状态码

3.4 "302"使用代理部分(get_html)

首先记得打开代理池

def get_proxy():
    try:
        response = requests.get(proxy_pool_url)
        if response.status_code == 200:
            return response.text
        return None
    except ConnectionError:
        return None



def get_html(url,count=1):
    print('Crawling',url)
    print('Trying Count',count)
    global proxy //全局变量proxy设为None,在最开始使用本机的IP进行访问
    
    if count >= max_count:
        print('Tried Too Many counts')
        return None
    try:
        if proxy:
            proxies = {
                'http':'http://' + proxy}
            response = requests.get(url ,allow_redirects=False , headers=headers, proxies=proxies)
        else:
            response = requests.get(url ,allow_redirects=False ,headers=headers)
        //由于requests会默认的处理302的跳转所以要加一个allow_redirects=False,来取消自动处理,才能拿到302的状态码
        //将headers作为参数传给resquests.get 传入cookies保证网页的登录状态
        if response.status_code == 200:
            return response.text
        if response.status_code == 302://需要设置一个代理
            print('302')
            proxy = get_proxy()
            if proxy:
                print('using proxy',proxy)
                return get_html(url)
            else:
                print('Get Proxy Failed')
                return None
    except ConnectionError:
        print('Error Occurred')
        proxy = get_proxy() //出现异常以后,更换代理
        count += 1 //限制判断次数,避免死循环
        return get_html(url,count) //如果错误,则递归重试

可能仍会输出多次302,只是因为当前使用的代理池的IP是一个网络上免费的公用代理池同时被多次使用。
在这里插入图片描述

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值