当前位置: 首页 > web >正文

爬虫之代理池学习(一)

爬虫之代理池学习(一)

目录

  • 1、代理池概述
  • 2、代理池的设计
  • 3、实现代理的思路
  • 4、实现代理IP模型类
  • 5、代理IP的工具模块
  • 6、实现代理IP的校验模块

下一篇:爬虫之代理池学习(二)

1、代理池概述

1.1、什么是代理池
代理池就是由代理IP组成的池子,提供多个稳定可用的代理IP
1.2、为什么实现代理池
(1)爬虫时,最常见反爬手段,IP反爬:当同一个IP访问一个网站次数过多,频率过高,就会限制这个IP的访问,需要经常换IP来解决这个问题。
(2)免费代理都是非常不稳定的,10%可用已经很不错了
1.3、代理池开发环境

  • Windows
  • 开发语言:Python3
  • 开发工具:PyCharm
  • 使用的主要技术:
    • requests:发送请求,获取页面数据
    • lxml:使用XPATH从页面提取到我们想要的数据
    • pymongo:把提取到代理IP存储到MongoDB数据库中和从 MongoDB数据库中读取代理IP,给爬虫使用。
    • Flask:用于提供Web服务
2、代理池的设计

2.1、代理池的工作流程
在这里插入图片描述
2.2、代理池模块及其作用
代理池分五大核心模块

  • 爬虫模块:采集代理IP
    • ①从代理IP网站上采集代理
    • ②进行校验(获取代理响应速度,协议类型,匿名类型)
    • ③把可用代理IP存储到数据库中
  • 代理IP的校验模块:获取指定代理的响应速度,支持的协议及匿名程度
    • ①原因:网站上所有标注的响应速度,协议类型和匿名类型是不准确的
    • ②这里使用httpbin.org进行检测
  • 数据库模块:实现对代理IP的增删改查操作
    • ①这里使用MongoDB来存储代理IP
  • 检测模块:定时的对代理池中代理进行检测,保证代理池中代理的可用性
    • ①从数据库读取所有代理IP
    • ②对代理IP进行逐一检测,可用开启多个协程,以提高检测速度
    • ③如果该代理不可用,就让这个代理分数-1,当代理的分数为0,就删除该代理,如果检测到代理可用就回复为满分。
  • 代理IP服务接口:提供高可用的代理IP给爬虫使用
    • ①根据协议类型和域名获取随机的高质量代理IP
    • ②根据协议类型和域名获取多个高质量代理IP
    • ③根据代理IP,不可用域名,告诉代理池这个代理IP在该域名下可用,下次获取这个域名的代理ip时,就不会再获取这个代理ip了,从而保证代理IP高可用性。

代理池的其它模块

  • 数据模型:domain.py

    • 代理IP的数据模型,用于封装代理ip相关信息。
  • 程序启动入口:main.py

  • 工具模块:

    • 日志模块:记录日志信息
    • http模块:获取随机User-Agent的请求头
  • 配置文件:settings.py

    • 用于默认代理的分数,配置日志格式,文件,启动的爬虫,检验的间隔时间等。

2.3、代理池的项目结构
在这里插入图片描述

3、实现代理的思路

3.1、思路一

  • 依据项目设计的流程图,一步一步进行实现
  • 遇到依赖于其它模块的地方,暂停当前的模块,去实现其它模块中需要使用的功能
  • 其它模块实现后,再回来接着写当前模块

3.2、思路二

  • 先实现基础模块,这些模块不依赖于其它的模块,比如:数据模型,校验模块,数据库模块
  • 然后实现具体的功能模块,比如:爬虫模块,检测模块,代理API模块

3.3、对比

  • 思路1:按流程一步一步实现,,适合一个人独立完成,流程清晰。
  • 思路2:把项目拆分为多个相对独立的模块,每个人实现一个模块,分工合作,对最初设计要求比较高,需提前设计好要使用到的接口。
4、实现代理IP模型类

4.1、步骤:

  • 定义Proxy类,继承Object
  • 实现__init__方法,负责初始化,包含如下字段:
    • ①ip:代理的IP地址
    • ②port:代理IP的端口号
    • ③protocol:代理Ip支持的协议类型,http是0,https是1,http和https都支持是2.
    • ④nick_type:代理IP的匿名程度,高匿:0,匿名:1,透明:2
    • ⑤speed:代理Ip的响应速度,单位s
    • ⑥area:代理ip所在的地区
    • ⑦score:代理IP的评分,衡量代理的可用性;默认分支通过配置文件进行配置。
    • ⑧disable_domains:不可用域名列表,有些代理IP在某些域名下可用,但是在其它域名下不可用。
  • 在配置文件:settings.py中定义MAX_SCORE=50,表示代理IP的默认最高分数
  • 提供__str__方法,返回数据字符串

4.2、代码:
domain.py

from settings import MAX_SCORE
"""
#### 4、实现代理IP模型类
4.1、步骤:- 定义Proxy类,继承Object- 实现__init__方法,负责初始化,包含如下字段:
①ip:代理的IP地址
②port:代理IP的端口号
③protocol:代理Ip支持的协议类型。http是0,https是1,http和https都支持是2.
④nick_type:代理IP的匿名程度,高匿:0,匿名:1,透明:2
⑤speed:代理Ip的响应速度,单位s
⑥area:代理ip所在的地区
⑦score:代理IP的评分,衡量代理的可用性;默认分支通过配置文件进行配置。
⑧disable_domains:不可用域名列表,有些代理IP在某些域名下可用,但是在其它域名下不可用。- 在配置文件:settings.py中定义MAX_SCORE=50,表示代理IP的默认最高分数- 提供__str__方法,返回数据字符串
"""
class Proxy(object):def __init__(self,ip,port,protocol=-1,nick_type=-1,speed=-1,area=None,score=MAX_SCORE,disable_domains=[]):# ①ip:代理的IP地址self.ip = ip# ②port: 代理IP的端口号self.port = port# ③protocol: 代理Ip支持的协议类型。http是0,https是1,http和https都支持是2.self.protocol = protocol# ④nick_type: 代理IP的匿名程度,高匿:0,匿名:1,透明:2self.nick_type = nick_type# ⑤speed: 代理Ip的响应速度,单位sself.speed = speed# ⑥area: 代理ip所在的地区self.area = area# ⑦score:代理IP的评分,衡量代理的可用性;默认分支通过配置文件进行配置。self.score = score# ⑧disable_domains: 不可用域名列表,有些代理IP在某些域名下可用,但是在其它域名下不可用。self.disable_doamains=disable_domains# - 提供__str__方法,返回数据字符串def __str__(self):# 返回数据字符串return str(self.__dict__)

settings.py

# - 在配置文件:settings.py中定义MAX_SCORE=50,表示代理IP的默认最高分数
MAX_SCORE=50
5、代理IP的工具模块

5.1、日志模块
log.py

import sys
import logging
import settingsclass Logger(object):def __init__(self):# 获取一个logger对象self._logger = logging.getLogger()# 设置format对象self.formatter = logging.Formatter(fmt=settings.LOG_FMT,datefmt=settings.LOG_DATEFMT)# 设置日志输出# 设置文件日志模式self._logger.addHandler(self._get_file_handler(settings.LOG_FILENAME))# 设置终端日志模式self._logger.addHandler(self._get_console_handler())# 设置日志等级self._logger.setLevel(settings.LOG_LEVEL)def _get_file_handler(self,filename):'''返回一个文件日志handler'''# 1、获取一个文件日志handlerfilehandlerr = logging.FileHandler(filename=filename,encoding="utf-8")# 2、设置日志格式filehandlerr.setFormatter(self.formatter)# 3、返回return filehandlerrdef _get_console_handler(self):'''返回一个输出到终端日志handler'''# 1、获取一个输出到终端日志handlerconsole_handler = logging.StreamHandler(sys.stdout)# 2、设置日志格式console_handler.setFormatter(self.formatter)# 3、返回handlerreturn console_handler@propertydef logger(self):return self._logger
# 初始化并配置一个logger对象,达到单例的
# 使用时,直接导入logger就可以使用
logger = Logger().loggerif __name__ == '__main__':logger.debug("调试信息")logger.info("状态信息")logger.warning("警告信息")logger.error("错误信息")logger.critical("严重错误信息")

settings.py

# - 在配置文件:settings.py中定义MAX_SCORE=50,表示代理IP的默认最高分数
MAX_SCORE=50# 日志的配置信息
import logging
LOG_LEVEL = logging.DEBUG    # 默认等级
LOG_FMT = '%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s: %(message)s'   # 默认日志格式
LOG_DATEFMT = '%Y-%m-%d %H:%M:%S'  # 默认时间格式
LOG_FILENAME = 'log.log'    # 默认日志文件名称

http.py

import random
"""
步骤:1、准备User-Agent的列表2、实现一个方法,获取随机user-agent的请求头
"""# 1、准备User-Agent的列表
USER_AGENTS = ["Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)","Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)","Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)","Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)","Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)","Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)","Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6","Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1","Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0","Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5","Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20","Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.11 (KHTML, like Gecko) Chrome/20.0.1132.11 TaoBrowser/2.0 Safari/536.11","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.71 Safari/537.1 LBBROWSER","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; LBBROWSER)","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E; LBBROWSER)","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.84 Safari/535.11 LBBROWSER","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E; QQBrowser/7.0.3698.400)","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; Trident/4.0; SV1; QQDownload 732; .NET4.0C; .NET4.0E; 360SE)","Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; QQDownload 732; .NET4.0C; .NET4.0E)","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.1; WOW64; Trident/5.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; Media Center PC 6.0; .NET4.0C; .NET4.0E)","Mozilla/5.0 (Windows NT 5.1) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 (KHTML, like Gecko) Chrome/21.0.1180.89 Safari/537.1","Mozilla/5.0 (iPad; U; CPU OS 4_2_1 like Mac OS X; zh-cn) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8C148 Safari/6533.18.5","Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:2.0b13pre) Gecko/20110307 Firefox/4.0b13pre","Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:16.0) Gecko/20100101 Firefox/16.0","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.11 (KHTML, like Gecko) Chrome/23.0.1271.64 Safari/537.11","Mozilla/5.0 (X11; U; Linux x86_64; zh-CN; rv:1.9.2.10) Gecko/20100922 Ubuntu/10.10 (maverick) Firefox/3.6.10"
]def get_request_headers():# 定义请求头return {'User-Agent': random.choice(USER_AGENTS),'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', # 接收类型'Accept-Language': 'en-US,en;q=0.5',  # 接收语言'Connection': 'keep-alive',  # 保持连接'Accept-Encoding': 'gzip, deflate',  # 压缩方式}# 2、实现一个方法,获取随机user-agent的请求头
if __name__ == '__main__':print(get_request_headers())print(get_request_headers())
6、实现代理IP的校验模块

6.1、步骤:

  • 检查代理IP速度和匿名速度:

    • 代理IP速度:从发送请求到获取响应的时间间隔 -
    • 匿名程度检查:
      • 对http://httpbin.org/get或https://httpbin.org/get发送请求
      • 如果响应的orign中有‘,’分割两个ip的就是透明代理ip
      • 如果 响应的headers 中包含 Proxy-Connection 说明是匿名代理IP
      • 否则就是高匿代ip
  • 检查代理ip协议类型

    • 如果http://httpbin.org/get发送请求可以成功,说明支持http协议
    • 如果https://httpbin.org/get发送请求可以成功,说明支持https协议

6.2、代码:
httpbin_validator.py

import time
import requests
import jsonfrom settings import TEST_TIMEOUT
from utils.http import get_request_headers
from utils.log import logger
from domain import Proxy"""
6、实现代理IP的校验模块
**6.1、步骤:**- 检查代理IP速度 和 匿名速度:- 代理IP速度:从发送请求到获取响应的时间间隔 -- 匿名程度检查:- 对http://httpbin.org/get或https://httpbin.org/get发送请求- 如果响应的orign中有‘,’分割两个ip的就是透明代理ip- 如果 响应的headers 中包含 Proxy-Connection 说明是匿名代理IP- 否则就是高匿代ip- 检查代理ip协议类型- 如果http://httpbin.org/get发送请求可以成功,说明支持http协议- 如果https://httpbin.org/get发送请求可以成功,说明支持https协议"""
def check_proxy(proxy):"""用于检查指定 代理IP 响应速度,匿名程度,支持协议类型:param proxy: 代理IP模型对象:return: 检查后的代理IP模型对象"""# 准备代理IP字典proxies = {'http':'http://{}:{}'.format(proxy.ip,proxy.port),'https':'https://{}:{}'.format(proxy.ip,proxy.port),}# 测试代理IPhttp,http_nick_type,http_speed = __check_http_proxies(proxies)https,https_nick_type,https_speed = __check_http_proxies(proxies,False)# 代理Ip支持的协议类型。http是0,https是1,http和https都支持是2.if http and https:proxy.protocol = 2proxy.nick_type = http_nick_typeproxy.speed = http_speedelif http:proxy.prptocol = 0proxy.nick_type = http_nick_typeproxy.speed = http_speedelif https:proxy.prptocol = 1proxy.nick_type = https_nick_typeproxy.speed = https_speedelse:proxy.prptocol = -1proxy.nick_type = -1proxy.speed = -1def __check_http_proxies(proxies,is_http=True):# 匿名类型:高匿:0,匿名:1,透明:2nick_type = -1# 响应速度,单位sspeed = -1if is_http:test_url = 'http://httpbin.org/get'else:test_url = 'https://httpbin.org/get'try:# 获取开始时间start = time.time()# 发送请求,获取响应数据response = requests.get(test_url,headers=get_request_headers(),proxies=proxies,timeout=TEST_TIMEOUT)if response.ok:# 计算响应速度speed = round(time.time()-start, 2)# 匿名程度# 把响应的json字符串转换为字典dic = json.loads(response.text)# 获取来源IP:orignorign = dic['orign']proxy_connection = dic['headers'].get('Proxy-Connection',None)if ','in orign:# -1 如果响应的orign中有‘,’分割两个ip的就是透明代理ipnick_type = 2# -2如果响应的headers中包含Proxy - Connection说明是匿名代理IPelif proxy_connection:nick_type = 1else:# -3否则就是高匿代ipnick_type = 0return True,nick_type,speedreturn False,nick_type,speedexcept Exception as ex:# logger.exception(ex)return False,nick_type,speed
if __name__ == '__main__':proxy = Proxy('',port='')print(check_proxy(proxy))

settings.py

# - 在配置文件:settings.py中定义MAX_SCORE=50,表示代理IP的默认最高分数
MAX_SCORE=50# 日志的配置信息
import logging
LOG_LEVEL = logging.DEBUG    # 默认等级
LOG_FMT = '%(asctime)s %(filename)s [line:%(lineno)d] %(levelname)s: %(message)s'   # 默认日志格式
LOG_DATEFMT = '%Y-%m-%d %H:%M:%S'  # 默认时间格式
LOG_FILENAME = 'log.log'    # 默认日志文件名称
# ---------------------
# 设置超时时间
TEST_TIMEOUT = 10
http://www.xdnf.cn/news/11530.html

相关文章:

  • Android-第十二节JSON解析第三方框架Gson,谈一谈Binder的原理和实现一次拷贝的流程
  • 蚂蚁集团智能部研究型实习腾讯大模型实习!
  • 中国高校BBS大全
  • AF_UNSPEC、AF_INET和AF_INET6之间的关系
  • mysql 1061报错_mysql主从 1061 log同步错误处理
  • [转载] SQL习题及答案
  • 分析Win7系统各种版本的区别 你的电脑适合哪个版本?
  • 192. Web前端网页制作 《你的名字》动漫主题网页设计实例 大学生期末大作业 html+css+js
  • C语言程序设计(第四版)—习题10程序设计题
  • Android OpenGL使用GLSurfaceView预览视频
  • 心脏出血(Heartbleed)漏洞浅析、复现
  • 【详解智能座舱通信技术--转载】
  • Android 2.3定制ROM CyanogenMod 7装机量超22万
  • 提示“QQ在线状态服务尚未启用,您需要添加对方为好友才能与其进行会话”解决方法
  • 奇妙动漫世界
  • 工业大数据浅析(上篇)——工业大数据的概念、发展及价值
  • 声屏障:声屏障
  • 软件开发的必备步骤
  • 超全的数据可视化图表组件,建议收藏!
  • 如何正确对待止损止盈?6大止损法、10种止盈技巧,让你的利润奔跑!
  • 在线代理(Web ProxyServer)完全详解
  • 全站静态化
  • 清除系统LJ(绿色单文件版)
  • 《大数据之路:阿里巴巴大数据实践》:看阿里人从IT时代走向DT时代的经验之谈!_大数据之路 阿里巴巴大数据实践 感悟(1)
  • 医院门诊排队叫号系统
  • offsetParent 深度解析
  • 继电器的工作原理及驱动电路
  • NSIS 下载
  • bluetooth外围设备找不到驱动程序怎么解决
  • 从数据库中取时间值,遇到:java.sql.Timestamp cannot be cast to java.lang.Long