网络抓取是一种强大的方法,可以让你从网站上收集数据,并将分散的非结构化信息转化为可操作的洞察力。但是,如果您不知道如何高效地进行网络搜索,这个过程往往会变得缓慢、令人沮丧,而且容易遇到各种挑战,如 IP 禁止、速率限制和服务器问题。
在本指南中,您将学习如何识别和克服可能导致网络搜索过程变慢的常见问题。
研究降低网络抓取速度的因素
当您开始刮擦更大的数据集时,您会遇到一些令人沮丧的挑战,从而减慢您的进程。常见的罪魁祸首包括以下几点:
- 高延迟:随着数据量的增加,请求往返服务器所需的时间也会增加。在搜索单个页面时,一秒钟的延迟可能没什么问题,但在搜索数百甚至数千个页面时,延迟就会变得更加明显。了解延迟及其来源可以帮助您确定需要优化的地方。有关高效 Python 搜刮设置的更多信息,请参阅我们的《使用 Python 进行网络搜刮》指南。
- 比率限制和验证码:你有没有试过在搜刮网站时被验证码击中?这就是速率限制的作用。网站使用这些限制来阻止人们过快地提出过多请求。如果网站认为您的请求过于频繁,验证码可能会被用作一种防御措施,从而减缓您的搜刮努力。
- 服务器拦截:网站越来越善于发现自动搜索器。如果他们认为你是一个机器人,他们可能会完全屏蔽你的 IP 地址。有效使用代理可以帮助你避免被发现–学习如何使用 Python代理来提高你的搜刮成功率。
- 复杂的网站结构:结构复杂、有大量动态渲染内容或 JavaScript 框架繁重的网站可能会给刮擦带来挑战。从复杂网站提取数据可能需要额外的工具和策略,从而增加了刮擦所需的时间和精力。要为此类任务选择合适的 HTTP 客户端,请查看此Python HTTP 客户端比较。
加速网络抓取
为了帮助您学习如何加快网络刮擦过程,本教程将教您如何刮擦Open Library(一个提供可扩展图书记录目录的网站)。
注意:在刮擦任何网站之前,请确保查看并遵守网站的隐私政策和使用条款。许多网站都有明确的禁止搜刮的规定,遵守这些政策至关重要。
了解和检查目标网页
在本教程中,您将为开放图书馆创建一个可提取有关鸟类书籍的搜索器。
首先需要检查网页元素,以确定 HTML 结构。为此,你可以右键单击网页的任何元素,然后选择 “检查“。这将打开浏览器的 “开发工具“,在这里你可以看到与网页各部分相关的 HTML 标记:

要抓取书名,需要检查页面并查看每个书名是否包含在特定结构中的 <h3>标记内的特定结构。
设置扫描环境
检查完页面的 HTML 之后,您需要设置一个 Python 环境。确保已安装Python 3.x 或更新版本,并在项目目录下创建一个虚拟环境:
python -m venv venv要激活环境,在 macOS 和 Linux 上运行源程序 venv/bin/activate,在 Windows 上运行venv\Scripts\activate即可。
激活环境后,安装以下库:
pip install requests beautifulsoup4
Requests用于向目标网站发送 HTTP 请求,Beautiful Soup用于解析网页的 HTML 内容。
执行基本网络抓取:顺序方法
为了演示手动搜索的工作原理,让我们来看看一个基本的搜索脚本。在搜索页面上搜索 “鸟类 “时,下面的代码会抓取返回的前 50 个页面。然后将它们保存到一个文件中:
import requests
from bs4 import BeautifulSoup
import time
# Create/open a file to write the titles
with open('book_titles.txt', 'w', encoding='utf-8') as f:
start_time = time.time()
# Loop through the first 50 pages
for page in range(1, 51):
url = f"https://openlibrary.org/search?q=birds&mode=everything&page={page}"
response = requests.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# Extract book titles from the current page
for book in soup.select('h3 > a'):
title = book.text
f.write(title + '\n')
print(f"{(time.time() - start_time):.2f} seconds")
该脚本使用 Requests 和 Beautiful Soup 库从开放图书馆网站上抓取与鸟类相关的书名。它向每个页面发送 HTTP GET 请求,使用select()方法提取书名,以找到 <a>标签嵌套在 <h3>标签,并将书名保存到名为book_titles.txt 的文件中。时间库测量整个搜索过程所需的时间。
要运行该脚本,请将其保存到名为app.py的文件中,然后在 75 Mbps 的连接上使用python app.py执行该脚本。该脚本耗时约 164 秒。请注意,这个时间可能因您的网络速度和硬件而异。
这种方法虽然简单,但由于每个请求都是按顺序发送的,因此速度会相当慢。此外,由于没有重试或优化,这种方法很容易受到 IP 屏蔽或速率限制等问题的影响。
应用优化
为了加快扫描过程并使其更加可靠,让我们应用一些优化技术:
使用 aiohttp 和 asyncio 执行并发请求
您可以并发地发送请求,而不是按顺序发送请求,以减少刮擦时间。Pythonaiohttp库是一个类似于 Requests 的 HTTP 客户端,允许你发送异步非阻塞 HTTP 请求。与管理异步操作的asyncio 结合使用,您可以高效地同时发送多个请求。
要使用 Python aiohttp 和 asyncio 库发送多个请求,首先要安装 aiohttp:
pip install aiohttp
下面是使用 aiohttp 和 asyncio 的优化版刮擦代码:
import aiohttp
import asyncio
from bs4 import BeautifulSoup
import time
async def fetch_and_process_page(session, url):
async with session.get(url) as response:
html = await response.text()
soup = BeautifulSoup(html, 'html.parser')
return [book.text for book in soup.select('h3 > a')]
async def main():
start_time = time.time()
async with aiohttp.ClientSession() as session:
with open('book_titles.txt', 'w', encoding='utf-8') as f:
# Create and execute tasks for all pages
tasks = [
fetch_and_process_page(session, url = f"https://openlibrary.org/search?q=birds&mode=everything&page={page}")
for page in range(1, 51)
]
results = await asyncio.gather(*tasks)
# Write all titles at once
for titles in results:
for title in titles:
f.write(title + '\n')
print(f"{(time.time() - start_time):.2f} seconds")
asyncio.run(main())
要运行这段代码,请创建一个名为async_scraper.py的新文件,并使用python async_scraper.py 运行它。
你会发现,与单请求方法相比,使用aiohttp大大缩短了刮擦时间。这次测试只用了 14.39 秒。
轮流使用代理服务器,避免 IP 堵塞
如果来自同一 IP 地址的请求过多,网站通常会阻止这些请求。避免这种情况的常用方法是使用代理,它是计算机和互联网之间的中介。它可以屏蔽你的 IP 地址,使你的请求看起来像是来自不同的地方。
为了进一步加强这一点,您可以使用轮流代理,将您的请求分配到多个 IP 上。在这种情况下,每个请求看起来都来自不同的 IP 地址,从而大大降低了被拦截的可能性。
您可以在网上找到免费的代理服务,或者使用从精心挑选的列表中返回免费代理服务的图书馆。请记住,免费代理服务会被许多用户共享,从而增加了被屏蔽的几率。要想获得更可靠、更高效的搜索结果,建议使用托管代理服务。这些服务提供旋转代理,可将您的请求自动分配到大量 IP 地址池中,确保更高的成功率和更快的性能。
下面是如何修改前面的脚本,以使用简单的旋转代理设置:
import requests
import random
from bs4 import BeautifulSoup
# List of proxies
proxies = [
"http://username:password@proxy1.provider.com:port",
"http://username:password@proxy2.provider.com:port",
"http://username:password@proxy3.provider.com:port"
]
# Loop through pages with rotating proxies
for page in range(1, 51):
url = f"https://openlibrary.org/search?q=birds&mode=everything&page={page}"
proxy = random.choice(proxies)
response = requests.get(url, proxies={"http": proxy, "https": proxy})
soup = BeautifulSoup(response.text, 'html.parser')
for book in soup.select('h3 > a'):
print(f"Scraped: {book.text}")
这段代码定义了一个代理列表,并使用 random.choice()函数为每个请求随机选择一个代理。这种方法可以让你轮流使用不同的代理服务器,大大降低了被拦截的风险。
轮流使用代理服务器对扫描大量数据尤其有用,因为它们能确保您的请求看起来来自不同的用户,从而使服务器更难将您识别为机器人。
添加重试逻辑
刮擦时,有些请求可能会因网络问题或速率限制而失败。实施自动重试可以帮助您使您的刮擦程序更加强大。
下面是一个如何使用请求库添加重试逻辑的示例:
import requests
from requests.adapters import HTTPAdapter
from requests.packages.urllib3.util.retry import Retry
from bs4 import BeautifulSoup
session = requests.Session()
retry = Retry(total=5, backoff_factor=1, status_forcelist=[429, 500, 502, 503, 504])
adapter = HTTPAdapter(max_retries=retry)
session.mount('http://', adapter)
session.mount('https://', adapter)
url = "https://openlibrary.org/search?q=birds&mode=everything&page=1"
response = session.get(url)
soup = BeautifulSoup(response.text, 'html.parser')
# Extract book titles
for book in soup.select('h3 > a'):
print(f"Scraped: {book.text}")
此代码片段使用了urllib3中的重试功能,以指数式延迟重试失败的请求,最多可重试五次。这意味着,如果请求失败,重试前会等待一段时间,每次失败都会增加等待时间。这种方法有助于确保临时问题(如网络故障或速率限制)不会完全阻止你的刮擦过程。
使用托管网络抓取器 API
虽然前面的优化很有用,但管理重试、代理和速率限制可能会很繁琐和耗时。或者,您可以使用受管理的Web Scraper API,它可以自动处理代理、绕过验证码并管理速率限制,从而无需人工干预并降低复杂性。API 专为可扩展性而设计,可以同时抓取数千个 URL,而不会有服务器封禁的风险。它还提供 JSON 或 CSV 等结构化格式的数据,便于将结果直接集成到您的项目中。
通过使用这种应用程序接口,您可以将更多精力放在分析数据和提取见解上,而不是维护刮擦基础设施。
使用预先收集的数据集节省时间
除了使用受管理的刮擦 API 外,您还可以使用预先收集的数据集进一步简化数据收集流程。这些数据集由 LinkedIn、亚马逊、Twitter 和 Airbnb 等一百多个热门网站汇编而成,涵盖了广泛的主题,可为您提供干净、随时可用的数据。利用这些数据集,您可以专注于分析数据和提取见解,同时避免数据收集的复杂性。
结论
要加快网络搜刮速度,需要结合技术优化和智能工具。在本指南中,您将探索以下内容:
- 刮削工作流程中的常见瓶颈
- 并发请求、重试和代理轮换等优化技术
- 受管理的 Web Scraper API 如何自动执行验证码和代理轮换等任务,以实现快速、可扩展的刮擦
无论您是独自工作还是在数据团队中工作,利用先进的工具和策略都能提高网络搜索流程的速度和可靠性。通过将高效的编码实践与托管服务相结合,您可以专注于真正重要的事情–从数据中提取可行的见解。
常见问题
有几个因素会降低网络搜刮速度,包括页面加载时间过长、JavaScript 过重的网站、速率限制、验证码和低效的搜刮代码。优化这些方面可以提高搜刮速度。
您可以通过使用异步请求、旋转代理、缓存数据、尽量减少不必要的请求以及利用无头浏览器或 API 来加快网络搜刮速度。
代理有助于将请求分发到多个 IP 地址,从而降低被拦截的几率。轮流使用代理服务器可以提高速度,并改善对受限内容的访问。
使用受管理的网络搜刮 API 可以节省时间和资源,因为它可以处理 IP 轮换、绕过验证码并确保可靠的数据提取,而无需大量编码。

Leave a Comment
Required fields are marked *