python打造爬虫代理池过程解析


Posted in Python onAugust 15, 2019

最近在使用爬虫爬取数据时,经常会返回403代码,大致意思是该IP访问过于频繁,被限制访问。限制IP访问网站最常用的反爬手段了,其实破解也很容易,就是在爬取网站是使用代理即可,这个IP被限制了,就使用其他的IP。对于高大上的公司来说,他们基本都使用收费的代理,基本不会有什么问题,比较稳定。像我这样的矮矬穷,肯定是用不起收费的代理。一般都是使用国内免费的代理,网上也有很多提供免费的代理。

很多人都是从网上爬取一批免费的代理IP,存放在存储媒介中,例如excel文件或者数据库。定时维护代理,保证代理可用。这个做法有个缺点,有些机器上并没有装有excel或者mysql、redis等数据库,这就导致了的代理池无法正常使用。

我之前是做java开发的,经常会把一些常用的数据放在ArrayList中,使用起来非常方便,效率高,因此借鉴之前在java方面的经验,将代理IP爬取下来存放在list列表中中,将list列表当做一个代理池,经常维护这个池里的代理。

我经常爬取免费代理的网站xicidaili swei360等,这些免费的代理足够我使用了,能够应付大多数的爬虫工作。爬取过程需要用到requests和pyquery库,没有安装的同学自行安装。

首先介绍下爬取xicidaili网站的过程, 要先定义一个方法用于抓取xicidaili网站的,参数有两个,一个是url,另外一个是要爬取代理网页的页数,也就是要爬几页,方法如下:

def get_xicidaili_proxy(url,page):
  for i in range(1,page):
    headers = {
      "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}
    response = requests.get(url + str(i), headers=headers)

    html = response.text
    doc = pq(html)
    ip_list = doc('#ip_list')('tr:gt(0)').items()
    for item in ip_list:
      ip = item.find('td:nth-child(2)').text()
      port = item.find('td:nth-child(3)').text()
      http_type = item.find('td:nth-child(6)').text()
      proxy_ip = http_type + "://" + ip + ":" + port
      if http_type == 'HTTP':
        http_proxy_pool.append(proxy_ip)
      elif http_type == 'HTTPS':
        https_proxy_pool.append(proxy_ip)
      # print(proxy_ip)

定义了http_proxy_pool和https_proxy_pool两个list变量,用于存储http类型和https类型的代理。 使用PyQuery根据css伪选择器提取出ip,端口和http类型信息,并按照http:// + ip+port的方式组合成一个字符串,存储在已经定义好的http_proxy_tool和https_proxy_pool变量中。

爬取swei360网站代理的方法就不贴出来了,原理和爬取xicidaili网站是一样的。

一个代理在使用之前要判断是否可用,我们使用request的get请求的返回代码判断代理是否可用,返回200,就说明代理可用,返回其他的代码就表示代理不可用,代码如下:

def detect_proxy(test_url,http_type,proxy):
  headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 SE 2.X MetaSr 1.0"}
  proxy={
    http_type : proxy
  }
  try:
    response = requests.get(test_url,proxies=proxy,headers=headers)
    if response.status_code in [200]:
      print('代理可用',proxy)
      return True
    else:
      print('代理不可用', proxy);
      delete_proxy(http_type,proxy)
      return False
  except(requests.exceptions.ProxyError,RequestException):
    print('代理不可用', proxy)
    delete_proxy(http_type, proxy)
    return False

定义了detect_proxy方法用于检测代理是否可用,有三个参数,分别是测试网址,代理类型(http和https)和代理IP。当requests的请求返回200代码时,就表示该代理可用,返回True,否则就是不可用,返回False。当遇到request异常或者其他的错误也认为代理不可用,返回False。对于不可用的代理,要从代理池中删除。

从代理池中获取代理时,我们使用的是从代理池中随机返回一个代理,这样就避免经常使用一个代理,从而遭到拒绝访问。代码如下:

def get_https_proxy():
  proxy_ip = random.choice(https_proxy_pool)
  return proxy_ip

def get_http_proxy():
  proxy_ip = random.choice(http_proxy_pool)
  return proxy_ip

为了保证代理的可用,当检测到一个代理不可用时,要及时的清理掉。就是从http_proxy_pool和https_proxy_pool列表中删除。

一个简单的爬虫代理池已经搭建好,总结下爬虫代理池搭建的过程:

  • 从免费的代理网站上爬取代理信息,存放在列表中。
  • 提供从代理池中随机获取代理的方法。http类型的网站要使用http类型的代理,https类型的网站要使用https类型的代理,因此分别提供获取http和https类型代理的方法。
  • 提供检测代理是否可用的方法,代理可用返回True,不可用返回False。
  • 提供删除代理的方法。

这个代理池其实相当的简单,有一个弊端就是在检测代理是否可用时,如果返回的不是200代码就认为代理不可用,返回其他代码的情况有很多,例如网络不可用、测试网站不可访问等。比较好的做法是给每个代理设置一个分值,例如10分,如果检测到不可用就减1,当分数为0时,就确定该代理不可用,直接从代理池中移除。检测到代理可用,就将分数设为10分。

这种做法给每个检测到不可用代理一个改邪归正的机会,不至于一刀切的抛弃掉。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持三水点靠木。

Python 相关文章推荐
python 从远程服务器下载东西的代码
Feb 10 Python
Python list操作用法总结
Nov 10 Python
python+unittest+requests实现接口自动化的方法
Nov 29 Python
使用python制作一个为hex文件增加版本号的脚本实例
Jun 12 Python
Python实现Singleton模式的方式详解
Aug 08 Python
python中如何使用insert函数
Jan 09 Python
Python生成词云的实现代码
Jan 14 Python
Python3.6 中的pyinstaller安装和使用教程
Mar 16 Python
基于python实现删除指定文件类型
Jul 21 Python
Python使用for生成列表实现过程解析
Sep 22 Python
pytest进阶教程之fixture函数详解
Mar 29 Python
Django模型层实现多表关系创建和多表操作
Jul 21 Python
使用selenium和pyquery爬取京东商品列表过程解析
Aug 15 #Python
如何爬取通过ajax加载数据的网站
Aug 15 #Python
Python K最近邻从原理到实现的方法
Aug 15 #Python
Python数据可视化 pyecharts实现各种统计图表过程详解
Aug 15 #Python
浅谈Python 敏感词过滤的实现
Aug 15 #Python
pycharm创建scrapy项目教程及遇到的坑解析
Aug 15 #Python
通过selenium抓取某东的TT购买记录并分析趋势过程解析
Aug 15 #Python
You might like
php中批量修改文件后缀名的函数代码
2011/10/23 PHP
解析PHP强制转换类型及远程管理插件的安全隐患
2014/06/30 PHP
PHP获取数组中重复最多的元素的实现方法
2014/11/11 PHP
php ucwords() 函数将字符串中每个单词的首字符转换为大写(实现代码)
2016/05/12 PHP
PHP中字符与字节的区别及字符串与字节转换示例
2016/10/15 PHP
php无限级分类实现方法分析
2016/10/19 PHP
javascript 复杂的嵌套环境中输出单引号和双引号
2009/05/26 Javascript
IE下写xml文件的两种方式(fso/saveAs)
2013/08/05 Javascript
将Datatable转化成json发送前台实现思路
2013/09/06 Javascript
Javascript:为input设置readOnly属性(示例讲解)
2013/12/25 Javascript
两种方法基于jQuery实现IE浏览器兼容placeholder效果
2014/10/14 Javascript
网页前端登录js按Enter回车键实现登陆的两种方法
2016/05/10 Javascript
JS 滚动事件window.onscroll与position:fixed写兼容IE6的回到顶部组件
2016/10/10 Javascript
jQuery插件HighCharts实现的2D条状图效果示例【附demo源码下载】
2017/03/15 Javascript
聊聊JavaScript如何实现继承及特点
2017/04/07 Javascript
Vue 2.0中生命周期与钩子函数的一些理解
2017/05/09 Javascript
vue.js,ajax渲染页面的实例
2018/02/11 Javascript
JavaScript 实现拖拽效果组件功能(兼容移动端)
2020/11/11 Javascript
[02:29]大剑、皮鞭、女装,这届DOTA2勇士令状里都有
2020/07/17 DOTA
利用Python实现颜色色值转换的小工具
2016/10/27 Python
python爬虫入门教程--快速理解HTTP协议(一)
2017/05/25 Python
python之从文件读取数据到list的实例讲解
2018/04/19 Python
pytorch对可变长度序列的处理方法详解
2018/12/08 Python
更新pip3与pyttsx3文字语音转换的实现方法
2019/08/08 Python
python3 动态模块导入与全局变量使用实例
2019/12/22 Python
浅谈pymysql查询语句中带有in时传递参数的问题
2020/06/05 Python
python字符串拼接+和join的区别详解
2020/12/03 Python
Html5 localStorage入门教程
2018/04/26 HTML / CSS
详解H5 活动页之移动端 REM 布局适配方法
2017/12/07 HTML / CSS
HTML5 HTMLCollection和NodeList的区别详解
2020/04/29 HTML / CSS
德国内衣、泳装和睡衣网上商店:Bigsize Dessous
2018/07/09 全球购物
2014年招商引资工作总结
2014/11/22 职场文书
2014年煤矿工人工作总结
2014/12/08 职场文书
2015年八一建军节活动总结
2015/03/20 职场文书
2015年工程师工作总结
2015/04/30 职场文书
java版 简单三子棋游戏
2022/05/04 Java/Android