ip代理服务器搭建代理服务器端口


登录线程IP池客户端时,默认情况下会自动切换IP。如果不想自动切换IP,或者还没有准备开始使用,请在客户端右侧将“在IP过期前几秒自动申请切换”设置为“0”。0无效。

默认情况下,线程IP池可以使用代理IP,而无需验证。如果需要在特定情况下允许使用,请选中“访问代理需要验证”。用户名和密码是用于登录线程IP池客户端的“TID”和“密码”,帐户验证允许使用。

许多用户退出线程IP池客户端后,发现浏览器无法访问网站。这是因为,以前在软件中一键设置浏览器代理IP,软件结束后,无法继续传输,因此无法访问网站。

在退出线程IP池软件之前,最好取消代理。如果忘记,请选择浏览器右上角的“工具”——“互联网选项”——“连接”——“局域网设置”(虽然因浏览器而异,但方法大致相同)、“为局域网使用代理服务器”

市面上有不少免费的代理IP服务,使用免费代理搭建动态IP池的方法非常常见,也是比较多人使用的一种。因为它是免费的,也就意味着无需成本,所以大多数人都因为“免费”二字而趋之若鹜。但是这种方法操作相对复杂一些,网上也有不少的教程分享,如果您感兴趣的话可以上网查找相关的项目,这边就不详细叙述如何爬取搭建了。

购买拨号服务器来搭建动态IP池也是很多朋友的选择。购买一定数量的服务器,然后花费一些时间来编写代码,或者结合网上的现成的软件,就可以将代理动态IP的池搭建起来了。这种方法搭建出来的IP池资源都是一个人独享的,工作起来效果还是不错的。只不过长期下来的话,服务器的维护成本较高,并且需要定时的维护,消耗大量的时间,如果是个人的话,搭建起来后期维护的成本太高了,如果您不是高端玩家的话,不建议使用这种方式搭建IP池。

选择购买代理IP服务的朋友很多,因为代理IP服务省时省力并且效果比较好。相对于免费的代理IP来说,收费代理IP虽然需要付出一定的成本,但是IP资源都是真实IP,并且高匿性,稳定性也好。

相比前两种搭建IP池的方法来说,付费代理IP更能满足用户的需求,但对于有些特殊要求的朋友来说,他们想一次提取很多个或者多次提取很多个,存放在本地建立的IP池里,这种方法在一定的程度上优化了方案。其中,像LumProxy这样的动态IP代理服务就深受大家的欢迎。LumProxy是国内领先的动态IP服务商,有着全球每一个国家和城市的9000多万IP。在每个国家每个大城市基本都涵盖,而且会不定时更换一些IP段。100%匿名高速代理,能够有效地帮助大家更好地工作。

代理IP池管理代理的集合及其相关IP地址。IP池中的代理类型决定了代理IP池的类型。一般情况下,根据代理ip池包含的代理类型,代理ip池有5种类型。
1、免费代理IP池。该免费代理IP池也称为公共IP池,它是管理免费代理的列表。IP一般是数据中心IP,但是在一些公共IP池中,你可以使用混合的住宅IP。可靠度,公共IP是最不可靠的代理池。由于很容易检测到公共代理服务器(也称为免费代理服务器),一些网站会默认阻止它,并在你不知情的情况下泄露你的真实IP地址。它们通常不需要任何形式的认证,直到被使用。在上,如果使用免费代理列表站点,则很容易建立公共IP池。为了创建一个公共IP池,您需要在上使用一个刮板为您获取免费代理,一个代理检查器来确保该池只包含有效的代理,以及IP循环系统等等。然而,你需要知道,使用公共IP池来进行任何合理的在线活动都不是个好主意——你会受到坏邻居、垃圾邮件和它们不可靠的特性的影响。
2、数据中心代理IP池。数据中心代理IP池是只包含数据中心IP的代理池。DataCenterIP是数据中心拥有和管理的IP。DataCenterBroker池具有与数据中心代理相关的所有优点,但也具有与数据中心代理相关的所有缺点。在数据中心代理池中的代理存在许多障碍,因为它们易于检测。

对于爬虫来说,当你的访问频率达到了目标网站的预警值时,就可能触发目标网站的反爬机制。而封禁访问者ip就是很常见的一个反爬机制。

当ip被封禁后,从此ip发出的请求将不能得到正确的响应。这种时候,我们就需要一个代理ip池。


1.池子里的ip是有生命周期的,它们将被定期验证,其中失效的将被从池子里面剔除。
2.池子里的ip是有补充渠道的,会有新的代理ip不断被加入池子中。
3.池子中的代理ip是可以被随机取出的。这样,代理池中始终有多个不断更换的、有效的代理ip,且我们可以随机从池子中取出代理ip,然后让爬虫程序使用代理ip访问目标网站,就可以避免爬虫被ban的情况。

今天,我们就来说一下如何构建自己的代理ip池。而且,我们要做一个比较灵活的代理池,它提供两种代理方式:


1.每次都通过http接口提取一个随机代理ip,然后在爬虫中使用此代理ip(大部分代理ip池服务都是这种形式)
2.使用squid3代理做请求转发,爬虫设置好squid3代理的地址,每次请求将由squid3自动转发给代理池中的代理项目已经放到了github上,不想看原理、只想应用的可以直接移步github:open_proxy_pool


1.代理IP的获取/补充渠道,定期把获取到的代理ip加入到代理池中
2.代理ip的验证机制,定期验证代理池中ip的有效性,并删除掉所有失效的ip3.一个web服务,用以提供获取一个随机代理的api4.squid3的维持脚本,它定期获取代理池中的可用ip,更新squid中的可转发代理列表
5.一个调度器,程序的入口,用来协调各组件的运行如果不是很理解,没关系,请往下看,我会细说。

1.redis服务器,用以存放代理池相关数据2.flask,用以实现提取单个随机代理的api3.squid3,用以实现代理转发组件1-获取代理ip的渠道我们有很多种渠道获取代理ip。笼统一点来说,可以分为两类,免费代理和收费代理。

免费代理,顾名思义嘛,最大的优点就是免费,不需要什么成本,网上搜一下就能找到。缺点也很明显,免费代理毕竟是免费的,所以质量根本不能保证,大部分无法使用,能用的多数也速度奇慢。

个人学习的话,如果真的资金优先,可以考虑采集免费代理;如果资金相对充裕,可以花钱买一天或一周的代理使用,价格也不贵。我是比较推荐收费代理的,因为免费代理的质量真的不敢恭维。

没用过收费代理的朋友可能不清楚,使用收费代理平台的接口,从平台上批量提取代理ip或使用代理时,一般都是要绑定你的机器ip的。比如,你的机器ip是123.123.123.123,你就需要事先在平台上把ip绑定为123.123.123.123,这样,你只能通过IP为123.123.123.123的机器从平台提取ip,提取出的ip也只能由ip为123.123.123.123的机器使用,其他ip的机器都不行。当我们有多台机器的时候,就会非常尴尬了,毕竟不能给每台机器都买一次代理吧,很不划算。

在站大爷上面,除了绑定ip这个方法外,还可以选择使用账号 密码提取/使用代理,选择这个方法的话就不再收到IP地址的限制。讲道理,有点舒服啊==

我先面的编码以站大爷为例,使用其他代理服务的可自行编写相关脚本,原理和逻辑都是相通的,部分细节上针对处理即可。

importrequestsimporttimeimportutilsimportsettingsfromgevent.poolimportPoolfromgeventimportmonkeymonkey.patch_all()classZdyIpGetter:“”"从站大爷上提取代理ip的脚本,使用其他代理服务的可自行编写相关脚本,原理和逻辑都是相通的,部分细节上需要针对处理“”"definit(self):#购买服务时,网站给出的提取ip的api,替换成自己的self.api_url=‘http://xxxxxxxxxxxxxxxxxxxxxxxxxx’self.logger=utils.get_logger(getattr(self.class,‘name’))self.proxy_list=[]self.good_proxy_list=[]self.pool=Pool(5)self.server=utils.get_redis_client()defcheck_proxy(self,proxy):“”"检查代理是否可用,并将可用代理加入到指定列表中:paramproxy::return:“”"ifsettings.USE_PASSWORD:tmp_proxy=‘{}:{}@{}’.format(settings.USERNAME,settings.PASSWORD,proxy)else:tmp_proxy=‘{}’.format(proxy)proxies={‘http’:‘http://’ tmp_proxy,‘https’:‘https://’ tmp_proxy,}try:#验证代理是否可用时,访问的是ip138的服务resp=requests.get(‘/ic.asp’,proxies=proxies,timeout=10)#self.logger.info(resp.content.decode(‘gb2312’))#判断是否成功使用代理ip进行访问assertproxy.split(‘:’)[0]inresp.content.decode(‘gb2312’)self.logger.info(‘[GOOD]-{}’.format(proxy))self.good_proxy_list.append(proxy)exceptExceptionase:self.logger.info(‘[BAD]-{},{}’.format(proxy,e.args))defget_proxy_list(self):“”"提取一批ip,筛选出可用的部分注:当可用ip小于两个时,则保留全部ip(不论测试成功与否):return:“”"whileTrue:try:res=requests.get(self.api_url,timeout=10).content.decode(‘utf8’)breakexceptExceptionase:self.logger.error(‘获取代理列表失败!重试!{}’.format(e))time.sleep(1)iflen(res)==0:self.logger.error(‘未获取到数据!’)elif‘bad’inres:self.logger.error(‘请求失败!’)#检测未考虑到的异常情况elifres.count(‘.’)!=15:self.logger.error(res)else:self.logger.info(‘开始读取代理列表!’)forlineinres.split():if‘:’inline:self.proxy_list.append(line.strip())self.pool.map(self.check_proxy,self.proxy_list)self.pool.join()#当本次检测可用代理数量小于2个时,则认为检测失败,代理全部可用iflen(self.good_proxy_list)>>>完成!=settings.FETCH_INTERVAL:self.fetch_new_ip()start=time.time()time.sleep(2)ifname==‘main’:ZdyIpGetter().main()说一下这里面的关键部分:

从平台上获取的ip是有生命周期的,一般几分钟后就会失效,所以我们需要用类似于字典的形式保存代理IP和它的过期时间为了更好地容错,我们将从平台上提取到的ip的生命周期统一设置为settings.PROXY_IP_TTL,而代理的可用时间一般是大于settings.PROXY_IP_TTL(我默认设置的是60s)。为了保证处理效率,实际使用的redis数据结构并非散列表(类似于python中的字典),而是zset(有序集合,可以为集合里面的每个元素设置一个分数,并能够分数来筛选区间内的元素)。这里,代理ip是zset中的元素,过期时间是元素的分数,参考上面的save_to_redis(self)代码。
2.如何验证提取到的ip是否可用?

提取到的ip有些可能是不能用的,所以我先进行了验证,再将有效的加入到代理池中使用ip138的接口验证代理是否生效校验之后,如果可用的ip非常少或全部失败,我倾向于认为是检验手段出了问题,并认为此批ip均为正常的,加入到代理池中组件2-检验并清理过期ip因为我给每个加入代理池的ip都设置了过期时间,所以检查代理ip是否有效这个操作,也并非真的去检验ip本身,而是检查它的过期时间。

importutilsimportsettingsimporttimeclassExpireIpCleaner:definit(self):self.logger=utils.get_logger(getattr(self.class,‘name’))self.server=utils.get_redis_client()defclean(self):“”"清理代理池中的过期ip:return:“”"self.logger.info(‘开始清理过期ip’)#计算清理前代理池的大小total_before=int(self.server.zcard(settings.IP_POOL_KEY))#清理self.server.zremrangebyscore(settings.IP_POOL_KEY,0,int(time.time()))#计算清理后代理池的大小total_after=int(self.server.zcard(settings.IP_POOL_KEY))self.logger.info(‘完毕!清理前可用ip{},清理后可用ip{}’.format(total_before,total_after))defmain(self):“”"周期性的清理过期ip:return:“”"whileTrue:self.clean()self.logger.info(‘*’*40)time.sleep(settings.CLEAN_INTERVAL)ifname==‘main’:ExpireIpCleaner().main()定期进行检测和清理,很简单,没有什么需要说的。

组件3-获取随机ip的web接口不得不说,使用flask开发简单的接口真的是太舒服了,简洁而快速。这个web服务提供两个小功能:

–coding:utf-8–@File:web_api.py@Author:AaronJny@Date:18-12-14上午11:22@Desc:提供http接口的web程序importutilsimportsettingsimportflaskimportrandomimporttimeredis_client=utils.get_redis_client()ip_pool_key=settings.IP_POOL_KEYapp=flask.Flask(name)@app.route(‘/random/’)defrandom_ip():“”"获取一个随机ip:return:“”"#获取redis中仍可用的全部ipproxy_ips=redis_client.zrangebyscore(ip_pool_key,int(time.time()),int(time.time()) settings.PROXY_IP_TTL*10)ifproxy_ips:ip=random.choice(proxy_ips)#如果ip需要密码访问,则添加ifsettings.USE_PASSWORD:ip=‘{}:{}@{}’.format(settings.USERNAME,settings.PASSWORD,ip.decode(‘utf8’))returnipelse:return‘’@app.route(‘/total/’)deftotal_ip():“”"统计池中可用代理的数量:return:“”"total=redis_client.zcard(ip_pool_key)iftotal:returnstr(total)else:return‘0’defmain():“”"程序运行入口:return:“”"app.run(‘0.0.0.0’,port=settings.API_WEB_PORT)ifname==‘main’:app.run(‘0.0.0.0’,port=settings.API_WEB_PORT)都很简单,就不细说了。

组件4-squid的维持、更新脚本处理http的接口外,我们还可以使用squid做代理转发,这样,在爬虫程序中就不需要再频繁地更换代理IP地址,直接填上squid的地址,它会自动帮你转发给其他代理ip。


1.从代理池中读取所有可用代理ip,作为可转发的代理列表写入到squid的配置文件中,并通过命令使squid重新加载配置文件。这样,squid一直使用最新可用的那些代理ip。
2.当squid服务异常时,通过命令杀死所有squid进程,并重新开启,保证服务正常运行下面的代码中使用了名为squid.conf的文件,此文件在github上,是关于squid的一些配置。如果需要对squid进行深度定制,需要自行修改这个文件。

importutilsimportsettingsimporttimeimportosimportsubprocessclassSquidKeeper:definit(self):self.logger=utils.get_logger(getattr(self.class,‘name’))self.server=utils.get_redis_client()self.ip_pool_key=settings.IP_POOL_KEY#区别对待使用密码和不使用密码的配置模板ifsettings.USE_PASSWORD:self.peer_conf=“cache_peer%sparent%s0no-queryproxy-onlylogin={}:{}never_directallowallround-robinweight=1connect-fail-limit=2allow-missmax-conn=
5 ”.format(settings.USERNAME,settings.PASSWORD)else:self.peer_conf=“cache_peer%sparent%s0no-queryproxy-onlynever_directallowallround-robinweight=1connect-fail-limit=2allow-missmax-conn=
5 ”defread_new_ip(self):“”"从redis中读取全部有效ip:return:“”"self.logger.info(‘读取代理池中可用ip’)proxy_ips=self.server.zrangebyscore(settings.IP_POOL_KEY,int(time.time()),int(time.time()) settings.PROXY_IP_TTL*10)returnproxy_ipsdefupdate_conf(self,proxy_list):“”"根据读取到的代理ip,和现有配置文件模板,生成新的squid配置文件并重新加载,让squid使用最新的ip。:paramproxy_list::return:“”"self.logger.info(‘准备加载到squid中’)withopen(‘squid.conf’,‘r’)asf:squid_conf=f.readlines()squid_conf.append(‘ #Cachepeerconfig ’)forproxyinproxy_list:ip,port=proxy.decode(‘utf8’).split(‘:’)squid_conf.append(self.peer_conf%(ip,port))withopen(‘/etc/squid/squid.conf’,‘w’)asf:f.writelines(squid_conf)failed=os.system(‘squid-kreconfigure’)#这是一个容错措施#当重新加载配置文件失败时,会杀死全部相关进行并重试iffailed:self.logger.info(‘squid进程出现问题,查找当前启动的squid相关进程…’)p=subprocess.Popen(“ps-ef|grepsquid|grep-vgrep|awk‘{print$2}’”,shell=True,stdout=subprocess.PIPE,universal_newlines=True)p.wait()result_lines=[int(x.strip())forxinp.stdout.readlines()]self.logger.info(‘找到如下进程:{}’.format(result_lines))iflen(result_lines):forproc_idinresult_lines:self.logger.info(‘开始杀死进程{}…’.format(proc_id))os.system(‘kill-s9{}’.format(proc_id))self.logger.info(‘全部squid已被杀死,开启新squid进程…’)os.system(‘servicesquidrestart’)time.sleep(3)self.logger.info(‘重新加载ip…’)os.system(‘squid-kreconfigure’)self.logger.info(‘当前可用IP数量{}’.format(len(proxy_list)))defmain(self):“”"周期性地更新squid的配置文件,使其使用最新的代理ip:return:“”"whileTrue:proxy_list=self.read_new_ip()self.update_conf(proxy_list)self.logger.info(‘*’*40)time.sleep(settings.SQUID_KEEPER_INTERVAL)ifname==‘main’:SquidKeeper().main()组件5-调度器调度器是程序的入口,也是对以上各个组件的控制和整合。


1.使用子进程分别开启各个组件
2.在某个组件异常退出后,重启它
3.接收到终止信号时,关闭所有存活的组件进程后再退出

–coding:utf-8–@File:scheduler.py@Author:AaronJny@Date:18-12-14上午11:41@Desc:调度中心,所有组件在这里被统一启动和调度importutilsimportsettingsfromget_ipimportZdyIpGetterfromdelele_ipimportExpireIpCleanerfromweb_apiimportappfromsquid_keeperimportSquidKeeperfrommultiprocessingimportProcessimporttime

classScheduler:logger=utils.get_logger(‘Scheduler’)@staticmethoddeffetch_ip():“”"获取新ip的进程:return:“”"whileTrue:try:ZdyIpGetter().main()exceptExceptionase:print(e.args)@staticmethoddefclean_ip():“”"定期清理过期ip的进程:return:“”"whileTrue:try:ExpireIpCleaner().main()exceptExceptionase:print(e.args)@staticmethoddefsquid_keep():“”"维持squid使用最新ip的进程:return:“”"whileTrue:try:SquidKeeper().main()exceptExceptionase:print(e.args)@staticmethoddefapi():“”"提供web接口的进程:return:“”"app.run(‘0.0.0.0’,settings.API_WEB_PORT)defrun(self):process_list=[]try:#只启动打开了开关的组件ifsettings.IP_GETTER_OPENED:#创建进程对象fetch_ip_process=Process(target=Scheduler.fetch_ip)#并将组件进程加入到列表中,方便在手动退出的时候杀死process_list.append(fetch_ip_process)#开启进程fetch_ip_process.start()ifsettings.EXPIRE_IP_CLEANER_OPENED:clean_ip_process=Process(target=Scheduler.clean_ip)process_list.append(clean_ip_process)clean_ip_process.start()ifsettings.SQUID_KEEPER_OPENED:squid_keep_process=Process(target=Scheduler.squid_keep)process_list.append(squid_keep_process)squid_keep_process.start()ifsettings.WEB_API_OPENED:api_process=Process(target=Scheduler.api)process_list.append(api_process)api_process.start()#一直执行,直到收到终止信号whileTrue:time.sleep(1)exceptKeyboardInterrupt:#收到终止信号时,关闭所有进程后再退出self.logger.info(‘收到终止信号,正在关闭所有进程…’)forprocessinprocess_list:ifprocess.is_alive():process.terminate()self.logger.info(‘关闭完成!结束程序!’)ifname==‘main’:Scheduler().run()公用方法和配置将各组件公用的方法和配置抽取出来,做了集中。

fromredisimportStrictRedis,ConnectionPoolimportsettingsimportloggingdefget_redis_client():“”"获取一个redis连接:return:“”"server_url=settings.REDIS_SERVER_URLreturnStrictRedis(connection_pool=ConnectionPool.from_url(server_url))defget_logger(name=name):“”"获取一个logger,用以格式化输出信息:paramname::return:“”"logger=logging.getLogger(name)logger.handlers.clear()logger.setLevel(logging.INFO)formatter=logging.Formatter(‘%(asctime)s-%(name)s-%(levelname)s:-%(message)s’,datefmt=‘%Y-%m-%d%H:%M:%S’)#使用StreamHandler输出到屏幕ch=logging.StreamHandler()ch.setLevel(logging.INFO)ch.setFormatter(formatter)logger.addHandler(ch)returnlogger涉及到的所有配置,可以根据情况进行修改:

REDIS_SERVER_URL=‘redis://:your_password@your_host:port/db_name’

PROXY_IP_TTL=60运行到这里,编码就完成了。打开终端,切换到项目根目录,输入python3scheduler.py运行即可。建议使用screen后台运行。


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