代理的使用

  • 代理池的维护
    • 代理池
    • 付费代理
    • ADSL拨号代理

代理池的维护

基本模块:

  • 存储模块: 使用Redis的有序集合负责存储抓取下来的代理,保证代理不重复
  • 获取模块:需要定时在各大代理网站抓取代理,代理的形式都是IP加端口,尽量从不同来源获取,尽量抓取高匿代理。
  • 检测模块:需要定时检测数据库中的代理,设置一个检测链接,最好是爬取哪个网站就检测哪个网站
  • 接口模块:需要用API来提供对外服务的接口,由于可用代理可能有多个,那么我们可以设置一个随机返回某个可用代理的接口,这样就能保证每个可用代理都可以取到实现负载均衡

代理池

存储模块:使用redis的有序集合,有序集合的每个元素都有一个分数字段,分数是可以重复的。根据分数对集合进行排序,可以作为判断一个代理是否可用的标志。

操作数据库的有序集合

MAX_SCORE=100
MIN_SCORE=0
INITIAL_SCORE=10
REDIS_HOST='localhost'
REDIS_PORT=6379
REDIS_PADDWORD=None
REDIS_KEY='proxies'
import redis
from random import choiceclass RedisClient(object):def __init__(self,host=REDIS_HOST,port=REDIS_PORT,password=REDIS_PADDWORD):"""初始化:param host:Redis 地址:param port: Redis 端口:param password: Redis 密码"""self.db=redis.StrictRedis(host=host,port=port,password=password,decode_responses=True)def add(self,proxy,score=INITIAL_SCORE):"""添加代理,设置分数为最高:param proxy: 代理:param score: 分数:return: 添加结果"""if not self.db.zscore(REDIS_KEY,proxy):return self.db.zadd(REDIS_KEY,score,proxy)#随机获取代理def random(self):"""随机获取有效代理,首先尝试获取最高分数代理,如果最高分数不存在,则按照排名获取,否则异常:return: 随即代理"""result=self.db.zrangebyscore(REDIS_KEY,MAX_SCORE,MAX_SCORE)if len(result):return choice(result)else:result=self.db.zrevrange(REDIS_KEY,0,100)if len(result):return choice(result)else:raise PoolEmptyError#检测代理无效时分数减1def decrease(self,proxy):"""代理值减一分,分数小于最小值,则代理删除:param proxy: 代理:return: 修改后的代理分数"""score=self.db.zscore(REDIS_KEY,proxy)if score and score > MIN_SCORE:print('代理',proxy,'当前分数',score,'减1')return self.db.zincrby(REDIS_KEY,proxy,-1)else:print('代理',proxy,'当前分数',score,'移除')return self.db.zrem(REDIS_KEY,proxy)#判断代理是否在集合def exists(self,proxy):"""判断是否存在:param proxy:代理:return: 是否存在"""return not self.db.zscore(REDIS_KEY,proxy)==None#设置代理分数def max(self,proxy):"""将代理设置为MAX_SCORE:param proxy: 代理:return: 设置结果"""print('代理',proxy,'可用,设置为',MAX_SCORE)return self.db.zadd(REDIS_KEY,MAX_SCORE,proxy)#返回当前集合的元素个数def count(self):"""获取数量:return:数量"""return self.db.zcard(REDIS_KEY)#返回所有的代理列表def all(self):"""获取全部代理:return: 全部代理列表"""return self.db.zrangebyscore(REDIS_KEY,MIN_SCORE,MAX_SCORE)

获取模块

import json
from .utils import get_page
from pyquery import PyQuery as pqclass ProxyMetaclass(type):def __new__(cls, name,bases,attrs):count=0attrs['__CrawlFunc__']=[]# 判断方法开头是否是Crawl,如果是则将其加入到__CrawlFunc__属性中,就成功将所有以crawl开头的方法定义成了一个属性,动态获取到所有以crawl开头的方法列表for k,v in attrs.items():if 'crawl_'in K:attrs['__CrawlFunc__'].append(k)count+=1attrs['__CrawlFuncCount__']=countreturn type.__new__(cls,name,bases,attrs)class Crawler(object,metaclass=ProxyMetaclass):def get_proxies(self,callback):proxies=[]for proxy in eval("self.{}()".format(callback)):print('成功获取到代理',proxy)proxies.append(proxy)return proxiesdef crawl_daili66(self,page_count=4):"""获取代理66:param page_count:页码:return: 代理"""start_url='http://www.66ip.cn/{}/html'urls=[start_url.format(page)for page in range(1,page_count+1)]for url in urls:print('Crawling',url)html=get_page(url)if html:doc=pq(html)trs=doc('.containerbox table tr:gt(0)').items()for tr in trs:ip=tr.find('td:nth-child(1)').text()port=tr.find('td:nth-child(2)').text()yield ':'.join([ip,port])def crawl_proxy360(self):"""获取Proxy360:return: 代理"""start_url='http://www.proxy360.cn/Regio.China'print('Crawling',start_url)html=get_page(start_url)if html:doc=pq(html)lines=doc('div[name="list_proxy_ip"]').items()for line in lines:ip=line.find('.tbBottomLine:nth-child(1)').text()port=line.find('.tbBottomLine:nth-child(2)').text()yield ':'.join([ip,port])def crawl_goubanjia(self):"""获取Goubanjia:return: 代理"""start_url='http://www.goubanjia.com/free/gngn/index.shtml'html=get_page(start_url)if html:doc=pq(html)tds=doc('td.ip').items()for td in tds:td.find('p').remove()yield td.text().replace(' ','')
#定义一个Getter类,用来动态调用所有以crawl开头的方法
from db import RedisClient
from crawler import Crawler
POOL_UPPER_THRESHOLD=10000class Getter():def __init__(self):self.redis=RedisClient()self.crawler=Crawler()def is_over_threshold(self):"""判断你是否达到了代理池的限制:return:"""if self.redis.count()>=POOL_UPPER_THRESHOLD:return Trueelse:return Falsedef run(self):print('获取器开始执行')if not self.is_over_threshold():for callback_label in range(self.crawler.__CrawFuncCount__):callback=self.crawler.CrawlFunc__[callback_label]proxies=self.crawler.get_proxies(callback)for proxy in proxies:self.redis.add(proxy)

检测模块

VALID_STATUS_CODES=[200]
TEST_URL='http://www.baidu.com'
BATCH_TEST_SIZE=100
class Tester(object):def __init__(self):self.redis=RedisClient()async def test_single_proxy(self,proxy):"""测试单个代理:param proxy: 单个代理:return: None"""conn=aiohttp.TCPConnector(verify_sal=False)async with aiohttp.ClientSession(connector=conn)as session:try:if isinstance(proxy,bytes):proxy=proxy.decode('utf-8')real_proxy='http://'+proxyprint('正在测试',proxy)async with session.get(TEST_URL,proxy=real_proxy,timeout=15) as response:if response.status in VALID_STATUS_CODES:self.redis.max(proxy)print('代理可用',proxy)else:self.redis.decrease(proxy)print('请求响应码不合法',proxy)except(ClientError,clientConnectorError,TimeoutError,AttributeError):self.redis.decrease(proxy)print('代理请求失败',proxy)#获取所有的代理列表def run(self):"""测试主函数:return: None"""print('测试器开始运行')try:proxies=self.redis.all()loop=asyncio.get_event_loop()#批量测试for i in range(0,len(proxies),BATCH_TEST_SIZE):test_proxies=proxies[i:i+BATCH_TEST_SIZE]tasks=[self.test_single_proxy(proxy) for proxy in test_proxies]loop.run_until_complete(asyncio.wait(tasks))time.sleep(5)except Exception as e:print('测试器发送错误',e.args)

接口模块

from flask import Flask,g
from db import RedisClient
__all__=['app']
app=Flask(__name__)def get_conn():if not hasattr(g,'redis'):g.redis=RedisClient()return g.redis
@app.route('/')
def index():return '<h2>Welcome to Proxy Pool System</h2>'@app.route('/random')
def get_proxy():"""获取随机可用代理:return: 随机代理"""conn=get_conn()return conn.random()
@app.route('/count')
def get_counts():"""获取代理池总量:return: 代理池总量"""conn=get_conn()return str(conn.count())

调度模块

TEST_CYCLE=20
GETTER_CYCLE=20
TESTER_ENABLD=True
GETTER_ENABLD=True
API_ENABLD=True
from multiprocessing import Process
from api import app
from getter import Getter
from tester import Testerclass Scheduler():def schedule_tester(self,cycle=TEST_CYCLE):"""定时测试代理:param cycle::return:"""tester=Tester()while True:print('测试器开始运行')tester.run()time.sleep(cycle)def schedule_api(self):"""开启API:return:"""app.run(API_HOST,API_PORT)def run(self):print('代理池开始运行')if TESTER_ENABLD:tester_process=Process(target=self.schedule_tester)tester_process.start()if GETTER_ENABLD:getter_process=Process(target=self.schedule_getter)getter_process=start()if API_ENABLD:api_process=Process(target=self.schedule_api())api_process.start()
if __name__ == '__main__':app.run()

付费代理

  • 讯代理:提供接口获取海量代理,按天或者按量收费。
  • 阿布云代理:搭建了代理隧道,直接设置固定域名代理。

ADSL拨号代理

ADSL通过拨号的方式上网,需要输入ADSL账号和密码,每次拨号就更换一个IP。

python爬虫--代理的使用相关推荐

  1. Python爬虫——代理和代理池

    文章目录 Python爬虫--代理和代理池 1.代理 2.代理池 Python爬虫--代理和代理池 1.代理 代理用处: 突破自身IP访问限制,访问国外资源 访问单位或公司内部资源 提高访问速度 隐藏 ...

  2. python爬虫代理的使用_从零开始写Python爬虫 --- 2.4 爬虫实践:代理的爬取和验证...

    爬网站的时候,由于各种原因,ip被锁了,这个时候我们就需要通过代理来突破封锁.网上有很多代理网站,付费和免费的都有,这次我们就来写一个scrapy爬虫,爬一些免费的代理下来用. 目标分析: 本次爬取了 ...

  3. python爬虫代理ip_Python爬虫如何获取代理ip及ip验证?

    如何获取大量的公开数据信息,这是我们互联网在竞争激烈的环境中的生存之道,不管在什么环境下都要学习和了解用户市场,客户需求,竞争对手,如何能获取到大量的数据信息,那么就需要用到网络爬虫. 在我们从事py ...

  4. Python爬虫代理ip异常和超时解决方案

    Python爬虫中的代理ip异常和超时如何解决?程序员在敲代码的过程中,一定会出现一定的错误,特别是像Python爬虫这种程序,并不能肯定每次请求都能保障稳定的返回同样的结果,例如反爬虫机制的强化,代 ...

  5. Python爬虫代理池

    爬虫代理IP池 在公司做分布式深网爬虫,搭建了一套稳定的代理池服务,为上千个爬虫提供有效的代理,保证各个爬虫拿到的都是对应网站有效的代理IP,从而保证爬虫快速稳定的运行,当然在公司做的东西不能开源出来 ...

  6. python 代理ip池_GitHub - xuan525/proxy_pool: Python爬虫代理IP池(proxy pool)

    ProxyPool 爬虫代理IP池 ______ ______ _ | ___ \_ | ___ \ | | | |_/ / \__ __ __ _ __ _ | |_/ /___ ___ | | | ...

  7. python 爬虫工具 butter_GitHub - TheButterflyOdor/proxy_pool: Python爬虫代理IP池(proxy pool)

    爬虫IP代理池 ______ ______ _ | ___ \_ | ___ \ | | | |_/ / \__ __ __ _ __ _ | |_/ /___ ___ | | | __/| _// ...

  8. python 爬虫代理_python 爬虫 使用代理 的问题

    刚刚在使用Python写爬虫,但是由于我在公司没有上网权限,所以借别人的账号用(opera 浏览器代理 可有上网),我将代理信息写在python脚本里面但是出现了下面的错误. 代码: import u ...

  9. python爬虫代理池_python爬虫之ProxyPool(代理ip地址池的构建)

    ProxyPool 安装 安装Python 至少Python3.5以上 安装Redis 安装好之后将Redis服务开启 配置代理池 cd proxypool 进入proxypool目录,修改setti ...

  10. Python爬虫-代理ip池建立

    代理IP池建立 前言 之前提到过urllib和requests的利用代理ip的访问方式 . https://blog.csdn.net/zhouchen1998/article/details/813 ...

最新文章

  1. STL中istream_iterator和ostream_iterator的基本用法
  2. 程序员计算器_GitHub 日收 7000 星,Windows 计算器项目开源即爆红!
  3. 永远不要在Linux执行的10个最危险的命令
  4. IOS开发笔记17-Object-C中的继承
  5. U-Boot移植教程之二:移植
  6. 【HDOJ】3948 The Number of Palindromes
  7. Lucene.net站内搜索—5、搜索引擎第一版实现
  8. Aho-Corasick automaton 模板
  9. nunjucks渲染富文本解析错误输出字符串而不是元素
  10. 【CodeForces - 471B】MUH and Important Things (模拟,细节)
  11. glibc交叉编译_TSN之linuxptp交叉编译
  12. JAVA入门级教学之(方法递归习题)
  13. js前端——滑稽官网的亮瞎眼系列滑稽大法
  14. 计算机视觉模型、学习和推理
  15. Mr.J-- jQuery学习笔记(三十一)--事件操作方法(onoff)
  16. linux命令详解——tee
  17. Keil MDK从未有过的详细使用讲解
  18. MyBatis3系列__03几个属性总结
  19. 【渝粤题库】陕西师范大学292111 社会学概论 作业
  20. qt5.15.1及以上版本进行编译(windows64位)

热门文章

  1. WaveDrom 时序图编辑器
  2. Git 版本控制系统的安装与使用
  3. CentOS7清理磁盘空间
  4. word中如何插入参考文献
  5. word文字间距设置教程
  6. 人工智能的利弊?好处和危害都有哪些
  7. IDEA 修改主题颜色
  8. 快速截图工具——百度输入法的扩展功能
  9. 卸载office2010后 再安装2013 错误1706 安装程序找不到需要的文件
  10. ImageAssitant插件 — 一件提取网页图片