首页 文章

如何重置/清除aiohttp会话

提问于
浏览
0

我一直在用aiohttp和反连接代理进行一些测试(每个请求的IP更改) . 使用反向连接代理的最大问题是,有时候你没有得到一个好的代理 . 无论如何,无论如何,我仍然需要通过该特定URL的请求 . 我创建了一个请求http://ip4.me 10,000次并检索IP地址的示例 . 一切都在一开始就有效,但最终,它开始出现错误:

赋值前引用的局部变量'ip'

出现此错误的原因是因为我在请求后获得的页面是一些重定向页面,它会将您带到一些随机站点 . 这是HTML(真的没关系,但我想我会画完整的图片) .

<html><head><meta content="2;url=http://ip4.me/?" http-equiv="refresh"/></head><body><iframe frameborder="0" id="f" style="width:1;height:1"></iframe><script>document.getElementById("f").src="http://168.126.130.229/tm/?a=CR&b=WIN&c=300017519516&d=32&e=2205&f=aXA0Lm1l&g=1520816781875&h="+Date.now()+"&y=0&z=0&x=1&w=2017-11-29&in=2205_00002350&id=20180312"</script></body></html>

我猜我得到这个页面,因为它是针对这么多请求的某种防御或类似的东西?现在通常当我收到请求的错误(错误的代理,花了很长时间加载等等)时,我只是继续尝试,直到我得到一个好的响应(在这个例子运行时90%的时间工作) . 就像我之前提到的,在最后(当可能有10个请求时) . 它将继续获取我上面发布的HTML和上面发布的错误 . 这将一遍又一遍地发生 .

我认为发生这种情况的唯一原因是正在使用相同的会话,因此网站以某种方式知道这一点并且不断给我这个重定向页面(从不允许它突破While循环) . 当然,还有另一个原因 . 如果有人对这种情况发生的原因有任何见解?或者甚至可能更好的方式来重试请求(如果我得到一个糟糕的代理等等),我将不胜感激!以下是我的完整工作示例,如果您有任何疑问,请与我联系 . 感谢您的时间!

import asyncio
import aiohttp

from bs4 import BeautifulSoup
from datetime import datetime
from aiohttp.resolver import AsyncResolver

class Proxy:
    def __init__(self, headers, proxy):
        self.headers = headers
        self.proxy = proxy

    async def build(self, dataset):
        tasks = []
        resolver = AsyncResolver(nameservers=["8.8.8.8", "8.8.4.4"])
        connector = aiohttp.TCPConnector(limit=1500, limit_per_host=0, resolver=resolver, use_dns_cache=False)
        async with aiohttp.ClientSession(connector=connector) as session:
            for data in range(0,dataset):
                task = asyncio.ensure_future(self.fetch(session, data))
                tasks.append(task)
            r = await asyncio.gather(*tasks)
            return r

    async def fetch(self, session, data):
        while True:
            try:
                async with session.get('http://ip4.me', headers=self.headers, proxy=self.proxy, timeout=60, ssl=False, allow_redirects=False) as resp:
                    assert resp.status == 200
                    r = await resp.read()
                    soup = BeautifulSoup(r, 'lxml')
                    for font in soup.find_all('font'):
                        ip = font.text
                    print (data, ip)
                    return ip
            except Exception as e:
                print (e)

if __name__ == '__main__':
    headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36'}
    proxy = 'XXX.XX.X.XXX:XXXXX'
    proxy = "http://{}".format(proxy)
    dataset = 10000

    px = Proxy(headers, proxy)

    startTime = datetime.now()
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)
    future = asyncio.ensure_future(px.build(dataset))
    ip = loop.run_until_complete(future)
    loop.close()
    print (datetime.now() - startTime)

1 回答

  • 2

    爬行是一个很大的话题 .

    在您的表达式中,我想象您正在使用不同的代理每个请求 . 但是在您的代码中,我认为您为每个请求使用相同的代理和相同的标头 .

    因此,在这种情况下,无论您如何在python代码中更改会话,服务器都很容易识别您 . 因为您的IP从未改变过 . 这就够了 . 当服务器认为您应该被禁止时,它会禁止您的IP,然后您将完全被阻止,无论您如何尝试 .

    有些网站提供专业服务来解决爬行禁止问题 . 它们在一段时间内为每个不同的请求使用不同的代理 . 并且他们使用随机生成的用户代理打扮成不同的浏览器 . 他们还使用庞大的数据库来决定相关策略 .

    所以这并不容易 . 如果您尝试获取一些数据,则可以放慢速度 .

    使用新会话

    ....
    resolver = AsyncResolver(nameservers=["8.8.8.8", "8.8.4.4"])
    connector = aiohttp.TCPConnector(limit=1500, limit_per_host=0, resolver=resolver, use_dns_cache=False, force_close=True)
    sessions = []
    for data in range(0,dataset):
        session = aiohttp.ClientSession(connector=connector)
        task = asyncio.ensure_future(self.fetch(session, data))
        tasks.append(task)
        sessions.append(session)
    r = await asyncio.gather(*tasks)
    [session.close() for session in sessions]
    return r
    ....
    

    force_close=True 可能没用,因为您为每个请求使用不同的会话 .

相关问题