代理
为什么要使用代理
- 让服务器以为不是同一个客户端在请求
- 防止我们的真实地址被泄露,防止被追究
通过上图可以看出:
-
正向代理:对于浏览器知道服务器的真实地址,例如VPN
-
反向代理:浏览器不知道服务器的真实地址,例如nginx
详细讲解:
正向代理是客户端与正向代理客户端在同一局域网,客户端发出请求,正向代理 替代客户端向服务器发出请求。服务器不知道谁是真正的客户端,正向代理隐藏了真实的请求客户端。 反向代理:服务器与反向代理在同一个局域网,客服端发出请求,反向代理接收请求 ,反向代理服务器会把我们的请求分转发到真实提供服务的各台服务器Nginx就是性能非常好的反向代理服务器,用来做负载均衡。
代理的使用
-
用法:
requests.get("http://www.baidu.com", proxies = proxies) -
proxies的形式:字典
-
例如:
proxies = { "http": "http://12.34.56.79:9527", "https": "https://12.34.56.79:9527", }
代理IP的分类
根据代理ip的匿名程度,代理IP可以分为下面四类:
-
透明代理(Transparent Proxy):透明代理的意思是客户端根本不需要知道有代理服务器的存在,但是它传送的仍然是真实的IP。使用透明代理时,对方服务器是可以知道你使用了代理的,并且他们也知道你的真实IP。你要想隐藏的话,不要用这个。透明代理为什么无法隐藏身份呢?因为他们将你的真实IP发送给了对方服务器,所以无法达到保护真实信息。
-
匿名代理(Anonymous Proxy):匿名代理隐藏了您的真实IP,但是向访问对象可以检测是使用代理服务器访问他们的。会改变我们的请求信息,服务器端有可能会认为我们使用了代理。不过使用此种代理时,虽然被访问的网站不能知道你的ip地址,但仍然可以知道你在使用代理,当然某些能够侦测ip的网页也是可以查到你的ip。
-
高匿代理(Elite proxy或High Anonymity Proxy):高匿名代理不改变客户机的请求,这样在服务器看来就像有个真正的客户浏览器在访问它,这时客户的真实IP是隐藏的,完全用代理服务器的信息替代了您的所有信息,就象您就是完全使用那台代理服务器直接访问对象,同时服务器端不会认为我们使用了代理。IPDIEA覆盖全球240+国家地区ip高匿名代理不必担心被追踪。
在使用的代理中,毫无疑问使用高匿代理效果最好。
从请求使用的协议可以分为:
-
http代理
-
https代理
-
socket代理等
不同分类的代理,在使用的时候需要根据抓取网站的协议来选择。
使用代理IP是怎么被别人发现并被查出真实IP的?
我们使用代理IP 后为什么还是会被发现,他们是怎么知道的呢相信大家一定很好奇,那我们一起看看都有哪些方法可以知道是不是使用了代理IP。
Keep-alive 报文:如果带有 Proxy-Connection 的 Keep-alive 报文,毫无疑问该IP是代理IP。
反向探测技术:扫描一下IP 开通80,8080等代理服务器经常开通的端口了吗,一般用户IP不太可能会开通如上的端口。
查看IP上端口:如果一个IP 中有的端口大于10000,该IP可能也不是普通用户。
HTTP头部的X Forward_For:开通了HTTP代理的IP可以通过此法来识别是不是代理,如果带有XFF信息,说明该IP是代理IP无疑。
REMOTE_ADDR是你的客户端跟你的服务器“握手”时候的IP。如果使用了“匿名代理”,REMOTE_ADDR将显示代理服务器的IP。
HTTP_CLIENT_IP是代理服务器发送的HTTP头。如果是“超级匿名代理”,则返回none值。同样,REMOTE_ADDR 也会被替为这个代理服务器的IP。
HTTP_VIA
$_SERVER['REMOTE ADDR'];//访问端(有可能是用户,有可能是代理的)IP。
$_SERVER['HTTP_CLIENT_IP'];//代理端的(有可能存在,也可以伪造)。
$_SERVER['HTTP_X_FORWARDED_FOR'];//用户是在哪个IP使用的代理(有可能存在,也可以伪造)
$_SERVER['HTTPVIA'];//是否使用代理
总结:平台有很多办法来检测,好用的IP代理,还是使用兔子IP。
代理IP使用的注意点
-
反反爬
使用代理ip是非常必要的一种
反反爬的方式但是即使使用了代理ip,对方服务器仍然会有很多的方式来检测我们是否是一个爬虫,比如:
-
一段时间内,检测IP访问的频率,访问太多频繁会屏蔽
-
检查Cookie,User-Agent,Referer等header参数,若没有则屏蔽
-
服务方购买所有代理提供商,加入到反爬虫数据库里,若检测是代理则屏蔽
所以更好的方式在使用代理ip的时候使用随机的方式进行选择使用,不要每次都用一个代理ip
-
-
代理ip池的更新
购买的代理ip很多时候大部分(超过60%)可能都没办法使用,这个时候就需要通过程序去检测哪些可用,把不能用的删除掉。
把免费的ip存起来? redis最合适,查询效率最高的.
-
代理服务器平台的使用:
当然还有很多免费的,但是大多都不可用需要自己尝试
import requests headers = { "User-Agent": "Mozilla/5.0 (Macintosh; IntelMac OS X 10_15_4) AppleWebKit/537.36 (KHTML, likeGecko) Chrome/87.0.4280.141 Safari/537.36" } proxies = { "http": "http://223.96.90.216:8085" } resp = requests.get("https://www.baidu.com",headers=headers, proxies=proxies) resp.encoding = 'utf-8' print(resp.text)
第三方代理
我们去百度找代理一般都是找一些免费的代理,很麻烦不说,稳定性是在堪忧。
所以市面上会有很多收费的代理提供给你使用,那么在我们的程序中如何引入第三方代理呢?
import requests
def get_ip():
while 1: # 反复提取代理IP
# 有待完善. 如果代理ip都用完了. 怎么办????
url = "https://dev.kdlapi.com/api/getproxy/?orderid=962349361442245&num=100&protocol=2&method=1&an_tr=1&quality=1&format=json&sep=1"
resp = requests.get(url)
ips = resp.json()
if ips['code'] == 0:
for ip in ips['data']['proxy_list']: # 拿到每一个ip
yield ip # 一个一个返回代理ip
print("所有IP已经用完, 即将更新!") # for循环结束. 继续提取新IP
else:
print("获取代理IP出现异常. 重新获取!")
def spider():
url = "https://www.baidu.com"
while 1:
try:
proxy_ip = next(gen) # 拿到代理ip
proxy = {"http": "http://" + proxy_ip,"https": "https://" + proxy_ip,}
resp = requests.get(url,proxies=proxy)
resp.encoding = "utf-8"
return resp.text
except :
print("报错了. ")
if __name__ == '__main__':
gen = get_ip() # gen就是代理ip的成成器
for i in range(10):
spider()
目录结构
-
get_ip.py 抓取免费ip
-
test_ip.py 测试ip是否可用
-
proxy_redis.py 存储和处理当前ip
-
app.py 获取当前可用的ip
-
settings.py 配置文件
-
main.py 启动程序
get_ip.py
'''
获取ip
'''
import requests
from lxml import etree
from proxy_redis import ProxyRedis
def get_ip():
redis = ProxyRedis()
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/107.0.0.0 Safari/537.36'
}
# url = 'http://www.66ip.cn/index.html'
# res = requests.get(url, headers=headers)
# data = res.content.decode('GBK')
# with open('66.html', 'w', encoding='UTF-8') as f:
# f.write(data)
with open('66.html', 'r', encoding='UTF-8') as f:
data = f.read()
tree = etree.HTML(data)
tr_list = tree.xpath('//*[@id="main"]/div[1]/div[2]/div[1]/table/tr/td[1]/text()|//*[@id="main"]/div[1]/div[2]/div[1]/table/tr/td[2]/text()')[2:]
for i in range(0, len(tr_list), 2):
ip = tr_list[i] + ':' + tr_list[i+1]
# ip 添加到redis中
redis.zset_add(ip)
print(ip, '存入redis')
if __name__ == '__main__':
get_ip()
test_ip.py
'''
测试ip
'''
from proxy_redis import ProxyRedis
import aiohttp
import asyncio
async def test_ip(sem, p_r, ip):
try:
async with sem:
async with aiohttp.ClientSession() as session:
async with session.get('http://httpbin.org/ip', proxy='http://'+ip, timeout=20) as resp:
con = await resp.text()
if con:
# 如果请求成功 则设置最大权重值
p_r.zset_add(ip)
else:
# 降低权重
p_r.zset_zincrby(ip)
print(ip, '降低权重')
except:
# 报错就是ip有问题 降低权重
p_r.zset_zincrby(ip)
print(ip, '降低权重')
async def main():
p_r = ProxyRedis()
# 获取所有ip
ip_list = p_r.get_all_ip()
# 创建信号量
sem = asyncio.Semaphore(100)
tasks = []
if ip_list:
for ip in ip_list:
tasks.append(asyncio.create_task(test_ip(sem, p_r, ip)))
await asyncio.wait(tasks)
def run():
while True:
try:
asyncio.run(main())
except:
pass
if __name__ == '__main__':
run()
proxy_redis.py
'''
对ip进行存储,获取,删除,权重处理等操作
'''
import random
import redis
from settings import *
class ProxyRedis:
def __init__(self):
'''
连接数据库
'''
self.r = redis.Redis(host=HOST, port=PORT, password=PASSWORD, db=DB, decode_responses=True)
# 添加ip
def zset_add(self, ip):
self.r.zadd(ZSET_NAME, {ip: SCORE})
# 关于权重的处理
def zset_zincrby(self, ip):
# 先查看当前ip权重为多少
score = self.r.zscore(ZSET_NAME, ip)
# 判断当前ip权重是否大于最小权重 大于则权重-1 否则删除ip
if score > MIN_SCORE:
# 当前权重-1
self.r.zincrby(ZSET_NAME, -1, ip)
else:
print(ip, '不可用 已删除')
# 删除ip
self.r.zrem(ZSET_NAME, ip)
# 获取所有ip
def get_all_ip(self):
return self.r.zrange(ZSET_NAME, 0, -1)
# 获取ip(获取可用ip)
def get_ip(self):
# 获取权重最高的ip
ip = self.r.zrangebyscore(ZSET_NAME, SCORE, SCORE, 0, -1)
if ip:
# 随机返回一个ip
return random.choice(ip)
# 下一轮的筛选 最小权重到最大权重区间的ip
ip = self.r.zrangebyscore(ZSET_NAME, MIN_SCORE, SCORE, 0, -1)
if ip:
# 随机返回一个ip
return random.choice(ip)
else:
print('无能为力了~')
app.py
'''
获取ip的
flask web框架
pip install flask
'''
from flask import Flask
from proxy_redis import ProxyRedis
# 实例化
app = Flask(__name__)
# 127.0.0.1:5000/
@app.route('/')
# @app.route('/get_ip/')
def index():
redis = ProxyRedis()
ip = redis.get_ip()
print(ip)
if ip:
return ip
return '来了老弟'
# 封装了启动功能的函数
def run():
app.run()
if __name__ == '__main__':
app.run(debug=True)
settings.py
'''
配置当前项目的配置文件
'''
# 对于当前redis连接的配置
HOST = '127.0.0.1'
PORT = 6379
DB = 0
PASSWORD = '123456'
# 对于redis中有序集合的配置
ZSET_NAME = 'proxy_redis'
SCORE = 100
MIN_SCORE = 70
main.py
'''
启动当前项目的
'''
from multiprocessing import Process
# 抓取ip
from get_ip import get_ip
# 获取可用ip
from app import run as app_run
# 测试ip
from test_ip import run as test_ip_run
def main():
Process(target=get_ip).start() # 开启获取ip进程
Process(target=app_run).start() # 开启获取可用ip进程
Process(target=test_ip_run).start() # 开启测试可用ip进程
if __name__ == '__main__':
main()


浙公网安备 33010602011771号