IP代理池学习记录

免责声明

        本文仅供学习和研究目的使用。所提供的信息和技术仅限于合规和合法的使用场景。请读者在应用相关技术时遵守法律法规,尊重他人的数据隐私和网站使用条款。本文作者对因使用本文信息而产生的任何法律责任或损失不承担责任


1、初识IP代理池

概述:在爬虫业务中,为了防止本机IP被封,可以使用IP代理来隐藏真实IP地址。因此代理的IP对于爬虫业务是非常的珍贵,对此,我们就尝试利用已学的知识白嫖免费的代理,由此产生了IP代理池。

简易IP代理池设计

  • DB 数据管理

    • Mongo
  • Fetcher 数据下载

    • 云代理
    • 快代理
  • Validata 数据验证

    • httpbin.org
    • 指定网站
  • Request 下载器

    • 专门下载工具
  • Scheduler 调度器

    • 协调各工具的使用
  • API API接口开发

    • FastAPI

      • 获取IP
      • 获取IP个数

2、日志模块(logging)

概述:logging模块是Python内置的标准模块,主要用于输出运行日志,可以设置输出日志的等级、日志保存路径、日志文件回滚等;

优点

①、通过设置不同的日志等级,在release版本中只输出重要信息,而不必显示大量的调试信息;

②、开发者可以决定将logging信息输出到什么地方,以及怎么输出;

日志级别从低到高:debug、info、warning、error,critical;

知识点补充:logging中默认只显示warning级别及以上等级的信息,如果想要显示debug或info级别的信息可以通过basicConfig调整默认等级,basicConfig除了能调整等级外还能控制日志的输出格式,将日志写入指定文件的功能:

# 演示的是将默认等级调整到info,不会显示debug级别的信息,format是设置日志的输出格式,可以根据需要自行调整
logging.basicConfig(level=logging.INFO,format='%(asctime)s %(levelname)s %(message)s',filename='文件名')

格式化设置

%(acstime)s 时间

%(filename)s 日志文件名

%(funcName)s 调用日志的函数名

%(levelname)s 日志的级别

%(module)s 调用日志的模块名

%(message)s 日志信息

%(name)s logger的name

实操:通过本实操掌握logging模块的基本用法(写入文件时是追加模式)。

import loggingformats = '%(asctime)s %(levelname)s %(message)s'
filenames = './mylog.log'
# 配置logging模块
logging.basicConfig(level=logging.INFO,format=formats,filename=filenames)def log_print():logging.debug('debug ...')logging.info('info ...')logging.warning('warn ...')logging.error('error ...')logging.critical('critical ...')if __name__ == '__main__':log_print()

运行后的mylog.log文件内容如下:


3、开发一个IP代理池

概述:本节将通过从零搭建IP代理池让大家了解搭建过程和思路。

文件结构

3.1、开发IP代理池的下载器

概述:在开发下载器前先创建一个名为config的python文件用于配置logging的相关信息,方便后面的开发直接使用:

config.py内容如下

import logginglevel = logging.DEBUG
format = '%(asctime)s --- %(filename)s --- %(levelname)s --- %(message)s'logging.basicConfig(level=level,format=format)

解决完日志的相关配置后,直接上手下载器的开发:

request_util.py内容如下

import requests
from fake_useragent import UserAgent
from config import logging
from lxml import etreeclass WebRequest:"""这是IP代理池的下载器"""def __init__(self):self.resp = Noneself.header = {'User-Agent':UserAgent().chrome}self.url = Nonedef get(self,url,header=None,*args,**kwargs):"""本函数主要用于发送get请求"""try:# 如果调用该方法时没有传值就使用类属性值中的请求头if not header:header = self.headerresp = requests.get(url,headers=header,*args,**kwargs)if resp.status_code == 200:resp.encoding = 'utf-8'self.resp = respreturn self.respexcept Exception as e:logging.warning(f'捕获的异常为{e}')def post(self, url, header=None, *args, **kwargs):"""本函数主要用于发送post请求"""try:# 如果调用该方法时没有传值就使用类属性值中的请求头if not header:header = self.headerresp = requests.get(url, headers=header, *args, **kwargs)if resp.status_code == 200:resp.encoding = 'utf-8'self.resp = respreturn self.respexcept Exception as e:logging.warning(f'捕获的异常为{e}')def analy_data(self):"""该函数用于解析数据"""# 解析响应数据e = etree.HTML(self.resp.content)return edef get_text(self):"""该函数用于获取响应的文本信息"""return self.resp.textdef get_json(self):"""该函数用于获取json数据"""return self.resp.json()def get_content(self):"""该函数用于获取数据流"""return self.resp.content

3.2、开发IP代理池的数据库模块

概述:我们将用mongo作为IP代理池的数据库,首先在db_util文件中创建一个名为db_util的类,然后在构造函数中连接数据库并指定要使用的集合,然后在这个类中创建多个类方法,用于实现①、插入数据;②、获取任意一条ip数据;③、统计某个请求类型的数量;④、删除IP及其对应的指纹;⑤、检测指纹是否存在。

db_util.py内容如下

import hashlib
import pymongo
from config import logging
from random import randint
class db_util():def __init__(self,host='localhost',port=27017):"""本函数用于连接客户端并获取指定数据库和集合"""# 连接Mongo客户端self.client = pymongo.MongoClient(host=host,port=port)# 选择数据库self.db = self.client.proxy# 选择ip集合self.ip = self.db.ip# 选择指纹集合self.finger = self.db.fingerdef insert(self,data):"""本函数用于向Mongo中插入数据data结构:{'type':'https','ip':'192.168.1.2','port':'4567'}"""# 获取data中的ipip = data.get('ip')# 对ip进行加密ip_finger = hashlib.md5(ip.encode()).hexdigest()# 在插入数据前判断该数据是否已经保存到数据库中if not self.exist_finger(ip_finger):# 插入数据到ip集合中self.ip.insert_one(data)# 将加密的ip插入到指纹集合中self.finger.insert_one({'ip':ip_finger})logging.info(f'成功保存了{data}')else:logging.info(f'该数据已经在数据库中啦:{data}')def get_one_ip(self,type='https'):"""本函数用于获取Mongo数据库中的任意一条数据"""# 获取当前数据库中有多少条指定类型的数据count = self.count(type)if count == 0:return Noneelif count == 1:one_data = self.ip.find_one({'type':type})else:# 如果有多条数据# 做分页处理,每页只有一条数据num = randint(0,count-1)one_data = self.ip.find({'type':type}).skip(num).limit(1)[0]return one_datadef count(self,type='https'):"""该函数用于获取数据库中指定类型的数据数量,起初设置该函数是为解决get_ip函数中find_one()方法默认只获取找到的第一条数据,导致可能会一直获取同一条数据的尴尬"""return self.ip.count_documents({'type':type})def delete(self,data):"""删除Mongo中指定的IP"""# 删除ip表中的指定数据ip_data = data.get('ip')self.ip.delete_one({'ip':ip_data})logging.info(f'{ip_data}删除成功')# 删除finger表中的指纹ip_finger = hashlib.md5(ip_data.encode()).hexdigest()self.finger.delete_one({'ip':ip_finger})def exist_finger(self,hash_id):"""判断指纹是否存在hash_id:是已经加密好的ip"""if self.finger.count_documents({'ip':hash_id}):logging.info(f'{id}已存在')return Trueelse:return Falsedef __del__(self):"""如果没有人调用数据库将自动销毁"""self.client.close()if __name__ == '__main__':mongo = db_util()# 向数据库中插入多条数据for i in range(10):mongo.insert({'type':'https','ip':f'192.168.1.{i}','port':'4567'})# 获取数据库中任意一条数据get_one_data = mongo.get_one_ip()print(f'获取的数据:{get_one_data}')# 删除数据库中的任意一条数据mongo.delete({'type':'https','ip':'192.168.1.4','port':'4567'})

运行结果如下:

集合ip的内容如下:

finger的内容如下:


3.3、开发IP代理池的验证模块

概述:验证IP地址是否有效主要是向httpbin.org/get发送请求,该网站会返回请求主机的IP,如果使用了代理去访问,返回的就是代理主机的IP。

validate.py内容如下

from request_util import WebRequest
from config import loggingdef validate_ip(proxy:dict) -> bool:http_url = 'http://www.httpbin.org/get'https_url = 'https://www.httpbin.org/get'ip_type = proxy.get('type') # 获取IP的请求类型ip_addr = proxy.get('ip') # 获取ipip_port = proxy.get('port') # 获取端口号# 构建代理proxies = {ip_type:f'{ip_type}://{ip_addr}:{ip_port}'}# 创建请求对象web = WebRequest()try:# 根据请求类型发送请求if ip_type == 'http':web.get(http_url,proxies=proxies,timeout=12)else:web.get(https_url,proxies=proxies,timeout=12)except:logging.info(F'该代理请求超时/请求失败:{ip_addr}')return False# 判断代理是否有效if web.resp:resp_ip = web.get_json().get("origin")# 防止origen有多个返回值if resp_ip.find(ip_addr) != -1:logging.info(f'该代理有效:{ip_addr}')return Trueelse:logging.info(f'该代理无效:{ip_addr}')return Falseelse:return False

3.4、开发解析模块

概述:本模块调用前面开发的下载器向目标代理网站发送请求,解析模块主要的任务是将代理网站中的指定数据获取出来并返回,这里我只解析了一个网站,实际开发中当然是多多益善了。fetcher_util.py内容如下

from request_util import WebRequest
from lxml import html
from time import sleep
import redef yun(page=2):"""本函数主要用于解析某代理网站的数据并将数据返回"""# 创建请求对象web = WebRequest()for i in range(1,page+1):sleep(3)# 目标网站url = (f'http://www.ip3366.net/free/?stype=3&page={page}')# 发送请求web.get(url)# 解析数据e = web.analy_data()for i in range(1,16):ips = e.xpath(f'//tr[{i}]/td[1]')[0]ip_about = html.tostring(ips, encoding='utf-8').decode('utf-8')# 这里尝试用切片直接截取,但只能切头不能去尾,最后还是采用正则去拿数据ip = re.search('<td>(.+)</td>', ip_about).group(1)ports = e.xpath(f'//tr[{i}]/td[2]')[0]port_about = html.tostring(ports, encoding='utf-8').decode('utf-8')# 这里尝试用切片直接截取,但只能切头不能去尾,最后还是采用正则去拿数据port = re.search('<td>(.+)</td>', port_about).group(1)types = e.xpath(f'//tr[{i}]/td[4]')[0]type_about = html.tostring(types, encoding='utf-8').decode('utf-8')# 这里尝试用切片直接截取,但只能切头不能去尾,最后还是采用正则去拿数据type = re.search('<td>(.+)</td>', type_about).group(1)yield {'ip':ip.lower(),'port':port,'type':type}# print({'ip':ip,'port':port,'type':type})if __name__ == '__main__':# 填入要获取的界面数量yun(1)

3.5、开发调度模块

dispatch_util.html内容如下:

from db_util import db_util # 导入数据库模块
from fetcher_util import yun # 导入代理数据网站解析
from validate_util import validate_ip # 导入验证ip的模块def start():"""本模块用于调度其它模块实现ip的获取,验证,保存/丢弃"""# 链接数据库mongo = db_util()# 下载IPfor proxy in yun(6):# 验证IPif validate_ip(proxy):# 保存IPmongo.insert(proxy)if __name__ == '__main__':start()

运行结果如下:

总结:通过IP代理池获取免费代理的结果相当炸裂,能用的极少,大家可以多解析几个免费网站尝试一下。


3.6、获取收费IP

概述:既然白嫖失败了就考虑为我们的IP代理池添加一个获取收费IP的函数,由于是收费IP,所以基本都没什么问题,我们直接获取收费IP的地址,然后直接获取即可:

fetcher_util文件添加如下内容

def money_player(num=2):"""本函数用于获取收费代理"""# 创建请求对象web = WebRequest()for i in range(num):url = '由代理网站提供,进入该地址就能看到网站提供的(多条)代理信息了,至少包含ip和port'resp = web.get(url)# 这里假设收费代理为我们提供了以下两条代理数据# 193.48.34.74:4789# 192.167.48.59:8874ip,port = resp.split(':'){'ip':ip,'type':'http','port':port}# 不同的网站可能还存在休眠要求,避免高频访问造成IP被封sleep(10)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/409537.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用ssm实现基于SSM的社区物业管理系统的设计与实现+vue

TOC ssm223基于SSM的社区物业管理系统的设计与实现vue 绪论 1.1 研究背景 现在大家正处于互联网加的时代&#xff0c;这个时代它就是一个信息内容无比丰富&#xff0c;信息处理与管理变得越加高效的网络化的时代&#xff0c;这个时代让大家的生活不仅变得更加地便利化&…

Redis—缓存机制

Redis 缓存机制 1. 缓存三兄弟1.1 缓存击穿1.2 缓存穿透1.3 缓存雪崩 2. 布隆过滤器3. 缓存和数据库数据一致性3.1 缓存更新策略3.2 缓存不一致处理 4. 热点 key4.1 热点 key 处理4.2 热点 key 重建 5. 缓存预热 Redis&#xff0c;一个轻量级的开源内存数据结构存储系统&#x…

Redis计数器:数字的秘密

文章目录 Redis计数器incr 指令用户计数统计用户统计信息查询缓存一致性 小结 技术派项目源码地址 : Gitee :技术派 - https://gitee.com/itwanger/paicodingGithub :技术派 - https://github.com/itwanger/paicoding 用户的相关统计信息 文章数&#xff0c;文章总阅读数&am…

go设计模式——单例模式

概念 单例是一种创建型设计模式&#xff0c;它确保一个类在整个程序运行期间只有一个实例&#xff0c;并提供一个全局访问点来使用该实例。虽然单例模式在某些情况下非常有用&#xff0c;例如管理全局配置、日志记录或资源共享&#xff0c;但它也带来了与全局变量相似的问题。…

redis面试(二十三)写锁释放

先加了写锁&#xff0c;后面再次加写锁或者读锁 anyLock: { “mode”: “write”, “UUID_01:threadId_01:write”: 2, “UUID_01:threadId_01”: 1 } 写锁的释放lua脚本在这里 RedissonWriteLock.unlockInnerAsync() 比如说现在的参数是这 KEYS[1] anyLock KEYS[2] redi…

SQL手工注入漏洞测试(MongoDB数据库)靶场通关攻略

构造数据回显 });return ({title:1,content:2 成功回显1,2&#xff0c;接下来我们开始尝试查询数据库 });return({title:tojson(db),content:2 得到之后我们就可以继续查询他的表名了 });return({title:tojson(db.getCollectionNames()),content:2 最后我们就可以爆出他表里的数…

宝塔面板配置FTP服务并安装内网穿透实现无公网IP远程连接

文章目录 前言1. Linux安装Cpolar2. 创建FTP公网地址3. 宝塔FTP服务设置4. FTP服务远程连接小结 5. 固定FTP公网地址6. 固定FTP地址连接 前言 本文主要介绍宝塔FTP文件传输服务如何搭配内网穿透工具&#xff0c;实现随时随地远程连接局域网环境搭建的宝塔FTP文件服务并进行文件…

ssrf实现.SSH未创建写shell

一、介绍SSRF漏洞 SSRF (Server-Side Request Forgery,服务器端请求伪造)是一种由攻击者构造请求&#xff0c;由服务端发起请求的安全漏洞。一般情况下&#xff0c;SSRF攻击的目标是外网无法访问的内部系统(正因为请求是由服务端发起的&#xff0c;所以服务端能请求到与自身相…

C语言基础——函数详解

目录 函数的概述 1 函数的概念 2 函数的意义 函数的定义和使用 1 函数的定义 2 函数的调用 2.1 在同一文件中函数定义后函数调用 2.2 在同一文件中函数定义前函数调用 2.3 调用其它文件中定义的函数 2.3.1 在函数调用文件中进行声明 2.3.2 在头文件中进行函数的声明 函…

图片工具箱:一键批量加水印,守护创意,提升效率!

前言 你是否曾在处理海量图片时&#xff0c;被繁琐的步骤和漫长的等待时间折磨得苦不堪言&#xff1f;是否梦想过拥有一款神器&#xff0c;能让你的图片处理工作变得轻松愉快&#xff0c;从此告别加班的烦恼&#xff0c;迎接升职加薪的曙光&#xff1f;那么&#xff0c;让我向…

有限差分学习笔记

有限差分介绍 ​ 在数学中&#xff0c;有限差分法&#xff08;finite-difference methods&#xff0c;简称FDM&#xff09;&#xff0c;是一种微分方程数值方法&#xff0c;是通过有限差分来近似导数&#xff0c;从而寻求微分方程的近似解。 由泰勒展开式的推导 显式方…

Web应用加密数据传输方案

目录 概述 最初的方案 改进后的方案 秘钥的过期时间 概述 介于公司最近发布了一个面向C端用户的Web系统&#xff0c;为防止前端调用后端的API接口时&#xff0c;数据传输的内容轻易的被黑客获取&#xff0c;而设计的一个前后端数据加密传输方案 最初的方案 在最开始&#xf…

2 种方式申请免费 SSL 证书,阿里云 Certbot

如何使用免费的 SSL 证书&#xff0c;有时在项目中需要使用免费的 SSL 证书&#xff0c;Aliyun 提供免费证书&#xff0c;三个月有效期&#xff0c;可以直接在aliyun 申请&#xff0c;搜索 SSL 证书&#xff0c;选择测试证书。 Aliyun 证书需要每三月来来换一次&#xff0c;页…

<数据集>车内视角行人识别数据集<目标检测>

数据集格式&#xff1a;VOCYOLO格式 图片数量&#xff1a;6470张 标注数量(xml文件个数)&#xff1a;6470 标注数量(txt文件个数)&#xff1a;6470 标注类别数&#xff1a;1 标注类别名称&#xff1a;[pedestrian] 序号类别名称图片数框数1pedestrian647029587 使用标注…

奔驰S迈巴赫S480升级动态按摩座椅效果怎么样

在迈巴赫 S480 的尊崇之旅中&#xff0c;舒适从未有尽头。现在&#xff0c;为您呈现前排动态按摩座椅的升级&#xff0c;将舒适体验提升至全新境界。 迈巴赫 S480 已然是舒适的代名词&#xff0c;但前排动态按摩座椅的升级&#xff0c;将为您带来前所未有的放松与享受。 当您…

网络UDP报文详细解析

目录 一、简介二、详细介绍三、其他相关链接1、TCP报文段的详细图总结2、TCP三次握手和四次挥手详解3、socket通信原理及相关函数详细总结4、网络包IP首部详细解析 一、简介 本文主要介绍UDP报文格式。 二、详细介绍 UDP是一种无连接、不可靠的用户数据报协议&#xff0c;其…

【注解】反序列化时匹配多个 JSON 属性名 @JsonAlias 详解

JsonAlias 注解是 Jackson 提供的一个功能强大的注解&#xff0c;允许一个字段在反序列化时匹配多个 JSON 属性名。它适用于在处理多种输入数据格式时&#xff0c;或当 JSON 数据的键名可能变化时。 一、JsonAlias 的作用 多种别名&#xff1a;JsonAlias 允许你为一个字段定义…

MySQL在Windows和Ubuntu上的安装与远程连接配置

MySQL是一个广泛使用的开源关系数据库管理系统&#xff0c;适用于各种操作系统。本文将详细介绍如何在Windows和Ubuntu系统上安装MySQL&#xff0c;并配置远程连接。 1. 在Windows上安装MySQL 1.1 下载MySQL安装包 首先&#xff0c;访问MySQL官方网站&#xff08;https://de…

UEFI 01记: 开发环境 在 ubuntu22 中搭建 edk2 开发环境并运行简单示例

https://uefi.org 1&#xff0c;预备环境 $ sudo apt install uuid-dev $ sudo apt install nasm $ sudo apt install bison flex $ sudo apt install build-essential $ sudo apt-get install x11proto-xext-dev $ sudo apt-get install libx11-dev $ sudo apt-get install l…

[数据集][目标检测]管道漏水泄漏破损检测数据集VOC+YOLO格式2614张4类

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;2614 标注数量(xml文件个数)&#xff1a;2614 标注数量(txt文件个数)&#xff1a;2614 标注…