Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python Can';使用asyncio时出现的错误页面无法清除_Python_Python 3.x_Web Scraping_Python Asyncio - Fatal编程技术网

Python Can';使用asyncio时出现的错误页面无法清除

Python Can';使用asyncio时出现的错误页面无法清除,python,python-3.x,web-scraping,python-asyncio,Python,Python 3.x,Web Scraping,Python Asyncio,我正在尝试使用文本文件中已有的一些链接提取不同属性的地址。我使用asyncio库创建了这个脚本。在遇到该站点抛出的这种类型的错误之前,脚本一直运行良好。我也检查了实现代理,但没有运气。虽然它肯定不是验证码页面,但在使用asyncio时,我在几次请求后就得到了该页面。仅供参考,当我进入请求模块时,我不会遇到该页面 我怎样才能摆脱那个错误页面 下面是我在文本文件中使用的一些 我试过: import asyncio import aiohttp import random import request

我正在尝试使用文本文件中已有的一些链接提取不同属性的地址。我使用asyncio库创建了这个脚本。在遇到该站点抛出的这种类型的错误之前,脚本一直运行良好。我也检查了实现代理,但没有运气。虽然它肯定不是验证码页面,但在使用asyncio时,我在几次请求后就得到了该页面。仅供参考,当我进入请求模块时,我不会遇到该页面

我怎样才能摆脱那个错误页面

下面是我在文本文件中使用的一些

我试过:

import asyncio
import aiohttp
import random
import requests
from bs4 import BeautifulSoup

async def get_text(session,url):
    async with session.get(url,ssl=False) as resp:
        assert resp.status == 200
        print("----------",str(resp.url))
        if "Error" in str(resp.url):raise
        return await resp.read()

async def get_info(sem,session,link):
    async with sem:
        r = await get_text(session,link)          
        soup = BeautifulSoup(r,"html.parser")
        try:
            address = soup.select_one("h1#mainaddresstitle").get_text(strip=True)
        except AttributeError: address = ""
        print(address)

async def main():
    sem = asyncio.Semaphore(5)
    with open("link_list.txt","r") as f:
        link_list = [url.strip() for url in f.readlines()]
        
    async with aiohttp.ClientSession(timeout=aiohttp.ClientTimeout(total=10)) as session:
        await asyncio.gather(
            *(get_info(sem,session,item) for item in link_list)
        )

if __name__ == '__main__':
    asyncio.run(main())
PS当脚本超过速率限制时,它应该会遇到一些页面,如
/Property/UsageValidation
,但不是
/Property/Error/?id=14e53e71-11b1-4f5e-a88c-f8a4721de99e
我尝试通过多次将您共享的URL复制到源文件来复制您的问题。通过这样做,我想模仿一组更大的不同URL的爬行。这是我学到的

  • 看起来你的利率是有限制的。至少我对你发布的代码有兴趣
  • 即使我使用VPN或代理,也会弹出
    UsageValidation
    页面
  • 我尝试过限制每台主机的连接数和/或连接总数,但没有效果
  • 在co例程之间设置延迟只会延长我点击
    UsageValidation
    wall之前的时间。注意,我一次又一次地点击相同的URL,所以这可能不具有代表性
以下是我成功获得最成功回复的代码:

import aiohttp
import asyncio

from bs4 import BeautifulSoup

headers = {
    "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/85.0.4183.121 Safari/537.36",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9",
    "Accept-Encoding": "gzip, deflate, br",
    "Accept-Language": "en-US,en;q=0.9,pl;q=0.8",
}


async def get_text(session, url):
    async with session.get(url) as resp:
        assert resp.status == 200
        print("----------", resp.url)
        return await resp.read()


async def get_info(sem, session, link):
    async with sem:
        r = await get_text(session, link)
        soup = BeautifulSoup(r, "html.parser")
        try:
            address = soup.select_one("h1#mainaddresstitle").get_text(strip=True)
            await asyncio.sleep(2)
        except AttributeError:
            address = ""
        print(address)


async def main():
    sem = asyncio.Semaphore(2)
    conn = aiohttp.TCPConnector(limit_per_host=2, limit=2)

    with open("source.txt") as f:
        link_list = [url.strip() for url in f.readlines()]

    async with aiohttp.ClientSession(
            connector=conn,
            headers=headers,
            timeout=aiohttp.ClientTimeout(total=5),
    ) as session:
        await asyncio.gather(
            *(get_info(sem, session, item) for item in link_list)
        )


if __name__ == '__main__':
    asyncio.run(main())
想法和解决方案:
  • 停止用数十个甚至数百个并发请求攻击这个(或任何其他)网站。为什么?因为,从本质上讲,您所做的是一个,因为您尝试尽可能快地连接到服务器
  • 通过在SO上共享代码,它将成为一个。对于大型服务,如LinkedIn或Facebook,这可能不太明显,但对于较小的服务器,这可能是危险的。话虽如此,即使是大公司也有严格的反刮政策和缓解技术
  • 至少等待一秒钟,然后再发送另一个请求。所需的暂停可能在
    robots.txt
    中定义为
    爬行延迟
    ,但从您的名字判断,您已经知道了
  • 删除多线程或至少限制线程数
  • 如果你已经访问过某个url,不要一次又一次地点击它。做一次你的工作,但要做好
  • 使用重试策略编写一个缓慢、连续的爬虫程序/刮板程序。为什么?因为,爬虫/刮板代码的主要目标应该是保持在雷达之下。最好是慢慢来,完成工作,而不是在几次请求和/或最终被禁止后惨败
  • 如果有API,请使用API

我猜您在某种程度上受到了速率限制,因为您只有在异步发出所有请求时才能获得这些页面。当脚本遇到该页面时,您希望它做什么?重试请求?我不想首先遇到该页面,因为在使用请求时我看不到该页面。我已经提到,即使在实现代理时,我仍然会看到该页面。所以,我非常怀疑这是因为利率限制。顺便说一句,当网站不喜欢任何机器人时,它就会开始抛出验证码。你被限制了费率。谢谢你的回答和建议@baduker。使用上面的脚本,我会得到相应的结果,直到出现包含
/Property/Error/
的链接。一旦那个错误链接起作用,我无论如何也摆脱不了它。包含
/Property/UsageValidation
的链接不是一个可以绕过的问题,我一开始就能够做到这一点。我只提到了这个链接
UsageValidation
,作为对我得到的评论的回复。