Python Can';使用asyncio时出现的错误页面无法清除
我正在尝试使用文本文件中已有的一些链接提取不同属性的地址。我使用asyncio库创建了这个脚本。在遇到该站点抛出的这种类型的错误之前,脚本一直运行良好。我也检查了实现代理,但没有运气。虽然它肯定不是验证码页面,但在使用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
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例程之间设置延迟只会延长我点击
wall之前的时间。注意,我一次又一次地点击相同的URL,所以这可能不具有代表性UsageValidation
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
/Property/Error/
的链接。一旦那个错误链接起作用,我无论如何也摆脱不了它。包含/Property/UsageValidation
的链接不是一个可以绕过的问题,我一开始就能够做到这一点。我只提到了这个链接UsageValidation
,作为对我得到的评论的回复。