Python 中网页抓取的当前问题和错误以及解决它们的技巧!

王林
发布: 2024-08-23 06:04:31
原创
1079 人浏览过

介绍

您好!我是 Max,一名来自乌克兰的 Python 开发人员,一位在网页抓取、数据分析和处理方面拥有专业知识的开发人员。

我的网络抓取之旅始于 2016 年,当时我正在为一家小公司解决潜在客户开发挑战。最初,我使用了现成的解决方案,例如 Import.io 和 Kimono Labs。然而,我很快就遇到了诸如阻塞、数据提取不准确和性能问题等限制。这促使我学习Python。在那些辉煌的日子里,requests 和 lxml/beautifulsoup 足以从大多数网站提取数据。如果您知道如何使用线程,那么您已经是一位受人尊敬的专家了:)

我们的一位社区成员撰写了此博客,作为对 Crawlee 博客的贡献。如果您想向 Crawlee 博客贡献此类博客,请通过我们的 Discord 频道与我们联系。

克劳利和阿皮皮

这是Apify和Crawlee的官方开发者社区。 | 8318 会员

Current problems and mistakes of web scraping in Python and tricks to solve them! 不和谐网站

作为一名自由职业者,多年来我为产品构建了小型解决方案和大型、复杂的数据挖掘系统。

今天,我想讨论 2024 年使用 Python 进行网页抓取的现实。我们将看看我有时会看到的错误以及您会遇到的问题,并为其中一些问题提供解决方案。

让我们开始吧。

只需接受请求和 beautifulsoup 即可开始赚很多钱......

不,这不是那种文章。

1.“我从服务器收到了 200 响应,但这是一个不可读的字符集。”

是的,这可能会令人惊讶。但我在六年前、四年前和 2024 年就看到过客户和开发者发来的这条消息。几个月前我在 Reddit 上读过一篇关于这个问题的帖子。

让我们看一个简单的代码示例。这将适用于 requests、httpx 和 aiohttp,只需全新安装且无需扩展。

import httpx

url = 'https://www.wayfair.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = httpx.get(url, headers=headers)

print(response.content[:10])
登录后复制

打印结果将类似于:

b'\x83\x0c\x00\x00\xc4\r\x8e4\x82\x8a'
登录后复制

这不是一个错误 - 这是一个完全有效的服务器响应。它以某种方式编码。

答案就在 Accept-Encoding 标头中。在上面的示例中,我只是从浏览器复制它,因此它列出了我的浏览器支持的所有压缩方法:“gzip、deflate、br、zstd”。 Wayfair 后端支持使用“br”(即 Brotli)进行压缩,并将其用作最有效的方法。

如果上面列出的库的标准依赖项中没有 Brotli 依赖项,则可能会发生这种情况。但是,如果您已经安装了 Brotli,它们都支持从此格式解压。

因此,安装适当的库就足够了:

pip install Brotli
登录后复制

这将使您获得打印结果:

b'<!DOCTYPE '
登录后复制

通过使用扩展进行安装,aiohttp 和 httpx 可以获得相同的结果:

pip install aiohttp[speedups]
pip install httpx[brotli]
登录后复制

顺便说一句,添加 brotli 依赖项是我对crawlee-python 的第一个贡献。他们使用 httpx 作为基本 HTTP 客户端。

您可能还注意到不久前出现了一种新的受支持的数据压缩格式 zstd。我还没有看到任何后端使用它,但是httpx将在0.28.0以上的版本中支持解压。我已经在我的项目中使用它来压缩服务器响应转储;它在使用 aiofiles 的异步解决方案中显示出令人难以置信的效率。

我见过的这种情况最常见的解决方案是开发人员停止使用 Accept-Encoding 标头,从而从服务器获得未压缩的响应。为什么这么糟糕? Wayfair 的主页未压缩时约 1 MB,压缩后约 0.165 MB。

因此,在没有此标头的情况下:

  • 您增加了互联网带宽的负载。
  • 如果您使用有流量的代理,则会增加每个请求的成本。
  • 您增加了服务器互联网带宽的负载。
  • 你暴露了自己是一个爬虫,因为任何浏览器都使用压缩。

但我认为问题比这更深层次。许多网络抓取开发人员根本不明白他们使用的标头的作用。因此,如果这适用于您,那么当您从事下一个项目时,请阅读这些内容;他们可能会让你大吃一惊。

2.“我在隐身浏览器中使用标头,但收到 403 响应”。这是 Johnn-...我是说,Cloudflare

是的,没错。 2023 年不仅为我们带来了 ChatGPT 等大型语言模型,还改进了 Cloudflare 保护。

那些长期从事网络抓取的人可能会说,“好吧,我们已经处理过 DataDome、PerimeterX、InCapsula 等。”

但是 Cloudflare 改变了游戏规则。它是世界上最大的 CDN 提供商之一,为大量网站提供服务。因此,许多站点都可以使用其服务,并且进入门槛相当低。这使得它与前面提到的技术完全不同,这些技术是在他​​们想要保护网站免遭抓取时有目的地实施的。

Cloudflare 就是为什么当您开始阅读另一门有关“如何使用 requests 和 beautifulsoup 进行网页抓取”的课程时,您可以立即关闭它的原因。因为你所学到的东西很可能根本无法在任何“体面”的网站上运行。

让我们看另一个简单的代码示例:

from httpx import Client

client = Client(http2=True)

url = 'https://www.g2.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = client.get(url, headers=headers)

print(response)
登录后复制

当然,响应是 403。

如果我们使用curl会怎样?

curl -XGET -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' 'https://www.g2.com/' -s -o /dev/null -w "%{http_code}\n"
登录后复制

还有403。

为什么会发生这种情况?

由于 Cloudflare 使用开发人员中流行的许多 HTTP 客户端的 TLS 指纹,站点管理员还可以根据这些指纹自定义 Cloudflare 阻止客户端的积极程度。

对于curl,我们可以这样解决:

curl -XGET -H 'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0"' -H 'Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8' -H 'Accept-Language: en-US,en;q=0.5' -H 'Connection: keep-alive' 'https://www.g2.com/' --tlsv1.3 -s -o /dev/null -w "%{http_code}\n"
登录后复制

You might expect me to write here an equally elegant solution for httpx, but no. About six months ago, you could do the "dirty trick" and change the basic httpcore parameters that it passes to h2, which are responsible for the HTTP2 handshake. But now, as I'm writing this article, that doesn't work anymore.

There are different approaches to getting around this. But let's solve it by manipulating TLS.

The bad news is that all the Python clients I know of use the ssl library to handle TLS. And it doesn't give you the ability to manipulate TLS subtly.

The good news is that the Python community is great and implements solutions that exist in other programming languages.

The first way to solve this problem is to use tls-client

This Python wrapper around the Golang library provides an API similar to requests.

pip install tls-client
登录后复制
from tls_client import Session

client = Session(client_identifier="firefox_120")

url = 'https://www.g2.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = client.get(url, headers=headers)

print(response)
登录后复制

The tls_client supports TLS presets for popular browsers, the relevance of which is maintained by developers. To use this, you must pass the necessary client_identifier. However, the library also allows for subtle manual manipulation of TLS.

The second way to solve this problem is to use curl_cffi

This wrapper around the C library patches curl and provides an API similar to requests.

pip install curl_cffi
登录后复制
from curl_cffi import requests

url = 'https://www.g2.com/'

headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:128.0) Gecko/20100101 Firefox/128.0",
    "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/png,image/svg+xml,*/*;q=0.8",
    "Accept-Language": "en-US,en;q=0.5",
    "Accept-Encoding": "gzip, deflate, br, zstd",
    "Connection": "keep-alive",
}

response = requests.get(url, headers=headers, impersonate="chrome124")

print(response)
登录后复制

curl_cffi also provides TLS presets for some browsers, which are specified via the impersonate parameter. It also provides options for subtle manual manipulation of TLS.

I think someone just said, "They're literally doing the same thing." That's right, and they're both still very raw.

Let's do some simple comparisons:

Feature tls_client curl_cffi
TLS preset + +
TLS manual + +
async support - +
big company support - +
number of contributors - +

显然,curl_cffi 在这次比较中获胜。但作为一名活跃用户,我不得不说,有时会出现一些非常奇怪的错误,我只是不确定如何处理。老实说,到目前为止,它们都还很原始。

我想我们很快就会看到其他库可以解决这个问题。

有人可能会问,Scrapy 怎么样?老实说:我并没有真正跟上他们的更新。但我还没有听说 Zyte 做了任何事情来绕过 TLS 指纹识别。因此,开箱即用的 Scrapy 也会被阻止,但没有什么可以阻止您在 Scrapy Spider 中使用curl_cffi。

3. 无头浏览器和 Cloudflare Turnstile 怎么样?

是的,有时我们需要使用无头浏览器。虽然说实话,但从我的角度来看,即使明显没有必要,它们也被频繁使用。

即使在无头的情况下,Cloudflare 的人们也通过创建一个名为 Cloudflare Turnstile 的怪物,设法让普通网络爬虫的日子变得困难。

要测试不同的工具,您可以使用此演示页面。

要快速测试库是否适用于浏览器,您应该从检查通常的非无头模式开始。您甚至不需要使用自动化;只需使用所需的库打开站点并手动操作即可。

哪些库值得为此检查?

候选人 #1 剧作家 + 隐秘剧作家

它会被阻止并且不会让你解决验证码。

Playwright 是一个很棒的浏览器自动化库。然而,开发人员明确表示,他们不打算将其开发为网络抓取工具。

而且我还没有听说过任何Python项目可以有效解决这个问题。

候选#2 unDetected_chromedriver

它会被阻止并且不会让你解决验证码。

这是一个相当常见的库,用于在 Python 中使用无头浏览器,在某些情况下,它允许绕过 Cloudflare Turnstile。但在目标网站上,它被阻止了。此外,在我的项目中,我还遇到过至少两种 Cloudflare 阻止 unDetected_chromedriver 的情况。

总的来说,unDetected_chromedriver 对于您的项目来说是一个很好的库,特别是因为它在底层使用了很好的旧 Selenium。

候选人 #3 botasaurus-driver

它允许您在点击后跳过验证码。

我不知道它的开发者是如何做到这一点的,但它确实有效。它的主要特点是它是专门为网页抓取而开发的。它还有一个更高级别的库可供使用 - botasaurus。

缺点是,到目前为止,它还很原始,botasaurus-driver 没有文档,并且有一个相当具有挑战性的 API 来使用。

总而言之,您用于无头浏览的主库很可能是 unDetected_chromedriver。但在一些特别具有挑战性的情况下,您可能需要使用botasaurus。

4. 框架呢?

高级框架旨在通过让我们专注于业务逻辑来加速和简化开发,尽管我们经常在灵活性和控制方面付出代价。

那么,2024 年的网页抓取框架有哪些?

刮痧

谈论 Python 网页抓取框架就不能不提到 Scrapy。 Scrapinghub(现在的 Zyte)于 2008 年首次发布它。16 年来,它一直作为一个开源库开发,开发公司在此基础上构建其业务解决方案。

说一下Scrapy的优点,可以单独写一篇文章。但我要强调的是他们两个:

  • 历年发布的海量教程
  • 中间件库由社区编写并正在扩展其功能。例如,scrapy-playwright。

但是有什么缺点吗?

近年来,Zyte更加专注于开发自己的平台。 Scrapy 大多只得到修复。

  • 缺乏绕过反抓取系统的开发。你必须自己实现它们,但是为什么需要框架呢?
  • Scrapy 最初是使用异步框架 Twisted 开发的。仅在 2.0 版本中添加了对 asyncio 的部分支持。查看源代码,您可能会注意到为此目的添加的一些解决方法。

因此,对于没有网络抓取保护的网站来说,Scrapy 是一个良好且经过验证的解决方案。您需要开发必要的解决方案并将其添加到框架中,以绕过反抓取措施。

波塔龙

使用浏览器自动化进行网页抓取的新框架,基于 botasaurus-driver 构建。首次提交于 2023 年 5 月 9 日进行。

先来说说它的优点:

  • 允许您使用 botasaurus-driver 绕过任何 Claudflare 保护以及许多其他保护。
  • 快速入门的良好文档

缺点包括:

  • 仅浏览器自动化,不适用于 HTTP 客户端。
  • 与botasaurus-driver紧密耦合;如果将来出现更好的东西,您将无法轻易替换它。
  • 没有异步,只有多线程。
  • 目前,它还很原始,仍然需要修复才能稳定运行。
  • 目前可用的培训材料很少。

这是一个很好的框架,可以快速构建基于浏览器自动化的网络爬虫。它缺乏灵活性和对 HTTP 客户端的支持,这对于像我这样的用户来说是一个难题。

Python 的 Crawlee

Python 生态系统中网络抓取的新框架。首次提交于 2024 年 1 月 10 日做出,并于 2024 年 7 月 5 日在媒体空间发布。

Current problems and mistakes of web scraping in Python and tricks to solve them! apify / 爬虫-python

Crawlee——一个用于 Python 的网络抓取和浏览器自动化库,用于构建可靠的爬虫。提取 AI、LLM、RAG 或 GPT 的数据。从网站下载 HTML、PDF、JPG、PNG 和其他文件。适用于 BeautifulSoup、Playwright 和原始 HTTP。有头模式和无头模式。通过代理轮换。

Current problems and mistakes of web scraping in Python and tricks to solve them!
网页抓取和浏览器自动化库

Current problems and mistakes of web scraping in Python and tricks to solve them! Current problems and mistakes of web scraping in Python and tricks to solve them! Current problems and mistakes of web scraping in Python and tricks to solve them! Current problems and mistakes of web scraping in Python and tricks to solve them!

Crawlee 涵盖了端到端的爬行和抓取,并且帮助您构建可靠的抓取工具。快。

? Crawlee for Python 向早期采用者开放!

即使使用默认配置,您的爬虫也会看起来几乎像人类一样,并且在现代机器人保护的雷达下飞行。 Crawlee 为您提供了在网络上抓取链接、抓取数据并将其持久存储为机器可读格式的工具,而无需担心技术细节。得益于丰富的配置选项,如果默认设置无法满足您的项目需求,您几乎可以调整 Crawlee 的任何方面。

在 Crawlee 项目网站上查看完整文档、指南和示例 ?

我们还有 Crawlee 的 TypeScript 实现,您可以在您的项目中探索和利用它。请访问我们的 GitHub 存储库,了解 GitHub 上 Crawlee for JS/TS 的更多信息。

安装

我们…


在 GitHub 上查看


由 Apify 开发,是其著名的 JS 框架crawlee 的 Python 改编版本,于 2019 年 7 月 9 日首次发布。

由于这是市场上的全新解决方案,目前正处于积极的设计和开发阶段。社区也积极参与其开发。所以,我们可以看到curl_cffi的使用已经在讨论中了。之前讨论过创建自己的基于 Rust 的客户端的可能性。希望公司不要放弃这个想法。

来自 Crawlee 团队:
“是的,我们肯定会在未来几年不断改进 Crawlee for Python。”

因为我个人希望看到由大公司开发和维护的 Python HTTP 客户端。 Rust 很好地展示了自己作为 Python 的库语言的能力。让我们至少记住 Ruff 和 Pydantic v2。

优点:

该框架是由网络抓取市场中的一家老牌公司开发的,该公司在该领域拥有完善的专业知识。

  • 支持浏览器自动化和 HTTP 客户端。
  • 完全异步,基于 asyncio。
  • 活跃的开发阶段和媒体活动。开发者倾听社区的声音,在这个阶段非常重要。

另外一点,它有一个非常好的模块化架构。如果开发人员引入在多个 HTTP 客户端之间切换的功能,我们将获得一个相当灵活的框架,使我们能够轻松更改所使用的技术,只需开发团队的简单实现。

不足:

  • 框架是新的。目前可用的培训材料很少。
  • 目前,它还很原始,仍然需要修复才能稳定运行,以及方便的配置界面。 - 除了更改会话和代理之外,目前没有任何方法可以绕过反抓取系统。但它们正在讨论中。

我相信crawlee-python 的成功主要取决于社区。由于教程数量较少,不适合初学者。然而,经验丰富的开发人员可能会决定尝试它而不是 Scrapy。

从长远来看,它可能是比 Scrapy 和 Botasaurus 更好的解决方案。它已经提供了灵活的工具来使用 HTTP 客户端、开箱即用地自动化浏览器以及在它们之间快速切换。然而,它缺乏绕过抓取保护的工具,它们在未来的实现可能是您选择框架的决定性因素。

结论

如果您已经读到这里,我想您会发现它很有趣,甚至可能有帮助:)

行业正在发生变化并带来新的挑战,如果您专业从事网络抓取,则必须密切关注情况。在其他一些领域,您将仍然是使用过时技术制造产品的开发人员。但在现代网络抓取中,您成为一名开发人员,制作的网络抓取工具根本不起作用。

此外,不要忘记您是更大的 Python 社区的一员,您的知识可用于开发使我们所有人的事情发生的工具。正如您所看到的,您需要的许多工具现在正在构建中。

我很高兴阅读您的评论。另外,如果您需要网络抓取专家或者只是想讨论这篇文章,您可以在以下平台找到我:Github、Linkedin、Apify、Upwork、Contra。

感谢您的关注:)

以上是Python 中网页抓取的当前问题和错误以及解决它们的技巧!的详细内容。更多信息请关注PHP中文网其他相关文章!

来源:dev.to
本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn
热门教程
更多>
最新下载
更多>
网站特效
网站源码
网站素材
前端模板