侯体宗的博客
  • 首页
  • Hyperf版
  • beego仿版
  • 人生(杂谈)
  • 技术
  • 关于我
  • 更多分类
    • 文件下载
    • 文字修仙
    • 中国象棋ai
    • 群聊
    • 九宫格抽奖
    • 拼图
    • 消消乐
    • 相册

Python搭建代理IP池实现获取IP的方法

Python  /  管理员 发布于 7年前   179

使用爬虫时,大部分网站都有一定的反爬措施,有些网站会限制每个 IP 的访问速度或访问次数,超出了它的限制你的 IP 就会被封掉。对于访问速度的处理比较简单,只要间隔一段时间爬取一次就行了,避免频繁访问;而对于访问次数,就需要使用代理 IP 来帮忙了,使用多个代理 IP 轮换着去访问目标网址可以有效地解决问题。

目前网上有很多的代理服务网站提供代理服务,也提供一些免费的代理,但可用性较差,如果需求较高可以购买付费代理,可用性较好。

因此我们可以自己构建代理池,从各种代理服务网站中获取代理 IP,并检测其可用性(使用一个稳定的网址来检测,最好是自己将要爬取的网站),再保存到数据库中,需要使用的时候再调用。

代码地址:https://github.com/Stevengz/Proxy_pool

另外三篇:
Python搭建代理IP池(二)- 存储 IP
Python搭建代理IP池(三)- 检测 IP
Python搭建代理IP池(四)- 接口设置与整体调度

本文介绍的则是构建代理 IP 池的第一步:获取 IP

使用的库:requests、pyquery

几个能提供免费代理的代理服务网站(排名不分先后):

厂商名称 地址
66代理 http://www.66ip.cn/
西刺代理 https://www.xicidaili.com
全网代理 http://www.goubanjia.com
云代理 http://www.ip3366.net
IP海 http://www.iphai.com
快代理 https://www.kuaidaili.com
免费代理IP库 http://ip.jiangxianli.com

代理服务网站 Crawler

代理获取的相关代码,把从每个网站提取 IP 的方法都放到一起,然后运行时只要调用相关方法即可

为了实现灵活,将获取代理的一个个方法统一定义一个规范,如统一定义以 crawl 开头,这样扩展的时候只需要添加 crawl 开头的方法即可

在这里实现了几个示例,如抓取代理 66、西刺代理、云代理、快代理 四个免费代理网站,这些方法都定义成生成器,通过 yield 返回。首先将网页获取,然后用 PyQuery 解析,解析出 IP 加端口形式的代理再返回

crawler.py

import jsonimport refrom utils import get_pagefrom pyquery import PyQuery as pq# 元类class ProxyMetaclass(type): def __new__(cls, name, bases, attrs):  count = 0  attrs['__CrawlFunc__'] = []  for k, v in attrs.items():   if 'crawl_' in k:    attrs['__CrawlFunc__'].append(k)    count += 1  attrs['__CrawlFuncCount__'] = count  return 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 proxies def crawl_daili66(self, page_count=4):  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_xicidaili(self):  for i in range(1, 3):   start_url = 'http://www.xicidaili.com/nn/{}'.format(i)   headers = {    'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8',    'Host':'www.xicidaili.com',    'Referer':'http://www.xicidaili.com/nn/3',    'Upgrade-Insecure-Requests':'1',   }   html = get_page(start_url, options=headers)   if html:    find_trs = re.compile('<tr class.*?>(.*?)</tr>', re.S)    trs = find_trs.findall(html)    for tr in trs:     find_ip = re.compile('<td>(\d+\.\d+\.\d+\.\d+)</td>')      re_ip_address = find_ip.findall(tr)     find_port = re.compile('<td>(\d+)</td>')     re_port = find_port.findall(tr)     for address,port in zip(re_ip_address, re_port):      address_port = address+':'+port      yield address_port.replace(' ','') def crawl_ip3366(self):  for i in range(1, 4):   start_url = 'http://www.ip3366.net/?stype=1&page={}'.format(i)   html = get_page(start_url)   if html:    find_tr = re.compile('<tr>(.*?)</tr>', re.S)    trs = find_tr.findall(html)    for s in range(1, len(trs)):     find_ip = re.compile('<td>(\d+\.\d+\.\d+\.\d+)</td>')     re_ip_address = find_ip.findall(trs[s])     find_port = re.compile('<td>(\d+)</td>')     re_port = find_port.findall(trs[s])     for address,port in zip(re_ip_address, re_port):      address_port = address+':'+port      yield address_port.replace(' ','') def crawl_kuaidaili(self):  for i in range(1, 4):   start_url = 'http://www.kuaidaili.com/free/inha/{}/'.format(i)   html = get_page(start_url)   if html:    ip_address = re.compile('<td data-title="IP">(.*?)</td>')     re_ip_address = ip_address.findall(html)    port = re.compile('<td data-title="PORT">(.*?)</td>')    re_port = port.findall(html)    for address,port in zip(re_ip_address, re_port):     address_port = address+':'+port     yield address_port.replace(' ','')

定义了一个 ProxyMetaclass,Crawl 类将它设置为元类,元类中实现了 new() 方法,遍历 attrs 变量即可获取类的所有方法信息,判断方法名前面是否是 crawl,是则将其加入到 CrawlFunc 属性中

代理网站的添加非常灵活,不仅可以添加免费代理,也可以添加付费代理,一些付费代理的提取方式类似,也通过 Web 的形式获取再进行解析,解析方式可能更加简单,如解析纯文本或 Json,解析之后以同样的方式返回,可以自行扩展

utils.py

import requestsfrom requests.exceptions import ConnectionErrorbase_headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/77.0.3865.120 Safari/537.36', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7'}def get_page(url, options={}): headers = dict(base_headers, **options) print('正在抓取', url) try:  response = requests.get(url, headers=headers)  print('抓取成功', url, response.status_code)  if response.status_code == 200:   return response.text except ConnectionError:  print('抓取失败', url)  return None

抓取网页内容的方法,访问链接成功后返回整个网页 HTML 内容,便于后续对网页具体内容的提取。封装成一个方法,让上面的 crawler 在抓取各个网站时调用

进行抓取

getter.py

from crawler import Crawlerfrom setting import *import sysclass Getter(): def __init__(self):  self.crawler = Crawler()  def run(self):  print('获取器开始执行')  for callback_label in range(self.crawler.__CrawlFuncCount__):   callback = self.crawler.__CrawlFunc__[callback_label]   # 获取代理   all_ip = self.crawler.get_proxies(callback)if __name__ == '__main__': get = Getter() get.run()

运行结果:

网站上的免费 IP 就被成功抓取下来了,至于能不能用,就有待验证了

整个过程其实就是一个普通的爬虫,而且没什么反爬措施,能到用代理 IP 的地步,代码里面的访问、抓取部分的细节应该都看得懂

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


  • 上一条:
    Python搭建代理IP池实现存储IP的方法
    下一条:
    详解python statistics模块及函数用法
  • 昵称:

    邮箱:

    0条评论 (评论内容有缓存机制,请悉知!)
    最新最热
    • 分类目录
    • 人生(杂谈)
    • 技术
    • linux
    • Java
    • php
    • 框架(架构)
    • 前端
    • ThinkPHP
    • 数据库
    • 微信(小程序)
    • Laravel
    • Redis
    • Docker
    • Go
    • swoole
    • Windows
    • Python
    • 苹果(mac/ios)
    • 相关文章
    • 在python语言中Flask框架的学习及简单功能示例(0个评论)
    • 在Python语言中实现GUI全屏倒计时代码示例(0个评论)
    • Python + zipfile库实现zip文件解压自动化脚本示例(0个评论)
    • python爬虫BeautifulSoup快速抓取网站图片(1个评论)
    • vscode 配置 python3开发环境的方法(0个评论)
    • 近期文章
    • 在go中实现一个常用的先进先出的缓存淘汰算法示例代码(0个评论)
    • 在go+gin中使用"github.com/skip2/go-qrcode"实现url转二维码功能(0个评论)
    • 在go语言中使用api.geonames.org接口实现根据国际邮政编码获取地址信息功能(1个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf分页文件功能(0个评论)
    • gmail发邮件报错:534 5.7.9 Application-specific password required...解决方案(0个评论)
    • 欧盟关于强迫劳动的规定的官方举报渠道及官方举报网站(0个评论)
    • 在go语言中使用github.com/signintech/gopdf实现生成pdf文件功能(0个评论)
    • Laravel从Accel获得5700万美元A轮融资(0个评论)
    • 在go + gin中gorm实现指定搜索/区间搜索分页列表功能接口实例(0个评论)
    • 在go语言中实现IP/CIDR的ip和netmask互转及IP段形式互转及ip是否存在IP/CIDR(0个评论)
    • 近期评论
    • 122 在

      学历:一种延缓就业设计,生活需求下的权衡之选中评论 工作几年后,报名考研了,到现在还没认真学习备考,迷茫中。作为一名北漂互联网打工人..
    • 123 在

      Clash for Windows作者删库跑路了,github已404中评论 按理说只要你在国内,所有的流量进出都在监控范围内,不管你怎么隐藏也没用,想搞你分..
    • 原梓番博客 在

      在Laravel框架中使用模型Model分表最简单的方法中评论 好久好久都没看友情链接申请了,今天刚看,已经添加。..
    • 博主 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 @1111老铁这个不行了,可以看看近期评论的其他文章..
    • 1111 在

      佛跳墙vpn软件不会用?上不了网?佛跳墙vpn常见问题以及解决办法中评论 网站不能打开,博主百忙中能否发个APP下载链接,佛跳墙或极光..
    • 2016-10
    • 2016-11
    • 2018-04
    • 2020-03
    • 2020-04
    • 2020-05
    • 2020-06
    • 2022-01
    • 2023-07
    • 2023-10
    Top

    Copyright·© 2019 侯体宗版权所有· 粤ICP备20027696号 PHP交流群

    侯体宗的博客