自动爬取网上免费代理实战:接口模块篇
1. 接口模块说明
接口模块篇可以专注于把爬取得来的代理以json格式返回,以供我们的爬虫程序使用,从而避开存在反爬机制的网站。
想到接口开发,想要轻量和简单,选择Python编写的Flask Web应用框架再适合不过了。
2. 代码实现
代码环境:Python 3.9.1
第三方依赖包:flask
import json
from flask import Flask, g
from proxypool.storage.redisclient import redisClient
from flask import jsonify
from proxypool.untils.parse import bytes_convert_string
from proxypool.setting import REDIS_KEY
app = Flask(__name__)
@app.route("/")
def index():
"""
首页
访问入口`<host-ip>`
"""
return "<h2>Index Page</h2>" \
"<p>For example:</p>" \
"<p>'<host:port>/random',Get a proxy random</p>" \
"<p>'<host:port>./proxies',Get all proxy(including unavailable) a proxy format: ip:port,score</p>" \
"<p>'<host:port>/proxy/<num>',Get <num> proxy(including unavailable)</p>"
@app.route("/random")
def get_proxy():
"""
随机返回一个代理
访问入口`<host-ip>/random`
:return: 从redis中读取代理,如果读取失败则返回`{}`,如果读取成功则返回`{'proxy': proxy}`,比如proxy=59.55.164.6:3256
"""
g.redis = redisClient() if not hasattr(g, 'redis') else g.redis
g.proxy = g.redis.random_proxy(redis_key='proxies')
if g.proxy is not None:
return jsonify(proxy=g.proxy)
return {'proxy': {}}
@app.route("/proxies")
@app.route("/proxy/<num>")
def get_count(num=None):
"""
返回count个代理
访问入口`<host-ip>/proxy/<count>`,其中count是用户输入的数字,输入多少返回多少,超过redis上限则返回all
访问入口`<host-ip>/proxies`,返回所有代理
"""
g.redis = redisClient() if not hasattr(g, 'redis') else g.redis
all = g.redis.get_count(redis_key=REDIS_KEY)
if num is None:
# 当访问http://xxx/proxy时,返回all
g.count = all
else:
# 否则只要输入的num不超过all,输入多少返回多少
if int(num) > all:
g.count = all
else:
g.count = num
g.proxies = g.redis.get_all(redis_key=REDIS_KEY, start=0, num=g.count, withscores=True)
p = {}
for proxy in g.proxies:
p[bytes_convert_string(proxy[0])] = str(proxy[1]) # for examples: (b'121.232.148.77:3256', 8.0)
p = json.dumps(p)
return jsonify(count=g.count, proxy=p)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5555)
从上面代码中,看到带@app.route,就是路由,注册一个路径,也是我们常熟悉的接口地址+路径
。
支持的方式有以下:
<host-port>/
---->首页<host-port>/random
---->随机返回一个代理,分数高的优先级最高<host-port>/proxies
---->获取所有的代理<host-port>/proxy/<count>
---->获取count条代理
其中<host-port>
是主机ip加端口号,如下图使用<host-port>/proxies
获取所有的代理,其中代理按照score分数从低到高排序
3. 随机获取一个代理
接下来,从redis中获取一个高分数代理,然后对其测试使用,实现代码如下:
import requests
from loguru import logger
def get_proxy(proxy_url):
"""
随机获取一个代理
:return: 返回一个代理,比如:`1.2.4.8:6666`,如果没有找到代理则返回`{}`
"""
try:
res = requests.get(proxy_url).json()
return res.get('proxy', None)
except ConnectionError:
logger.error('get proxy error')
def test_proxy(proxy):
"""
测试一个代理
:proxy: 传入一个代理,比如:`113.93.224.2:3256`
"""
if not len(proxy):
logger.error(f'没有获取到代理,请等待...')
logger.debug(f'获得一个代理:{proxy} 正在测试是否可用...')
try:
res = requests.get('http://httpbin.org/get', proxies={'http': f'http://{proxy}'}, timeout=5)
if res.status_code == 200:
print(res.text)
origin = res.json().get('origin')
proxy_ip = proxy.split(":")[0]
assert origin == proxy_ip
logger.success("代理可用", f'{proxy_ip}')
except Exception as e:
logger.error(f'代理 {proxy} 失败 {e}')
if __name__ == '__main__':
proxy_url = 'http://127.0.0.1:5555/random'
proxy = get_proxy(proxy_url)
test_proxy(proxy)
测试代理结果如下:
参考:https://cuiqingcai.com/7048.html
完整代码:https://github.com/rosaany/proxypool