通常,教程侧重于技术方面,即你可以复制的内容:“从这儿开始,按这条路走,你就会到达那儿。”这对学习特定技术非常有帮助,但有时候很难理解作者为什么选择这样的方式做事,或是什么在他们的开发过程中起指导作用。
如果您也想为Crawlee Blog写一篇类似的博客,请通过我们的discord频道联系我们。我们社区的一位成员为此撰写了一篇博客。
Crawlee & Apify (爬虫和自动化工具交流群)这是Apify和Crawlee的官方开发者社区,拥有8987成员。
这是 Discord 网站的图标和链接:discord.com
在这篇博客里,我会讲一讲我在做网页抓取项目时遵循的一些基本原则,这些原则帮助我在项目中取得了不错的成果。
所以,让我们来探索一下网页抓取开发者的心态。
1. 选择项目的数据源(为项目选择数据源):当你开始一个项目的时候,你可能需要从某个目标站点提取特定数据。检查该网站或应用程序提供了什么样的数据提取功能。这里有一些可能的选择:
官方 API
- 网站可能提供一个免费的官方 API,通过它你可以获取所有必要的数据。这是最好的选择之一。例如,如果你需要从Yelp
提取数据,可以考虑这种方法。网站
- 在这种情况下,我们研究网站的结构,以及前端与后端的交互方式。手机应用
- 在某些情况下,可能根本没有网站或 API 的情况下,或者手机应用提供了更多的数据,在这种情况下,不要忘记采用中间人代理(如:中间人代理
)的方法。
如果一个数据源失效了,尝试访问其他可用的数据源。
以Yelp
为例,有这三个选项,如果官方API
不适合你,你可以尝试其他两个。
robots.txt
和 站点地图
文件。
我认为大家或多或少都了解过 robots.txt
和 sitemap
,但我也经常看到有人会忘记它们。如果你是第一次听说这些词,这里给你一个简单的说明:
robots
是 SEO 中常用的爬虫名称。这通常指的是像 Google、Bing 等主要搜索引擎或工具中的爬虫。robots.txt
是一个描述机器人行为规则的文件。它包括允许访问的爬虫用户代理、两次页面扫描之间的等待时间、禁止扫描的页面模式等。这些规则通常基于哪些页面应被搜索引擎索引,哪些不应被索引。sitemap
描述了网站结构,帮助机器人更好地导航。它也有助于扫描只需更新的内容,从而减少对网站的额外负载。
既然你不是Google
或其他任何流行的搜索引擎,robots.txt
中的规则可能对你不利,但结合站点地图文件sitemap
,这是一个很好的地方来研究网站的结构、预期与机器人的互动以及非浏览器用户代理(如爬虫)。在某些情况下,这可以简化从网站中提取数据的过程。
例如,使用Crawlee网站的sitemap
,你可以轻松地获取整个博客的所有历史时期或特定时间段内文章的直接链接。只需进行一次简单的检查,你就不需要实现分页逻辑了。
全面的网站分析是创建有效网络爬虫的一个重要前提条件,特别是如果你不想使用浏览器自动化工具。然而,这样的分析需要很多时间。
值得注意的是,花在分析和寻找更优爬取方案上的时间并不总是有回报——你可能会花上数小时才发现最显而易见的方法其实一直都是最有效的。
因此,这样做是很明智的。在最初的网站分析上设定一些限制。如果你在分配的时间内没有找到更好的方法,退而采用更简单的方法。随着你积累更多的经验,你将能够更早地判断,根据网站所使用的技术,是否有必要花更多时间进行分析。
此外,在只需要从一个网站提取一次数据的项目中,详细的网站分析有时可以不再需要编写任何抓取代码。例如,这里有一个这样的网站示例 - https://ricebyrice.com/nl/pages/find-store
。
通过分析,你会发现,所有数据只需要发送一个请求就能得到。你只需将这些数据从浏览器复制到一个 JSON 文件里,任务就大功告成了。
分析网站时,切换排序和页面之间的选项,同时并与网站上的各种元素进行互动,同时观察浏览器的开发者工具中的“网络”标签。这将帮助你更好地理解网站是如何与后端进行交互的,它是基于哪种框架构建的,以及可以对其产生什么样的预期行为。
5. 数据不是凭空产生的这一点很明显,但在项目工作时需牢记。当你看到数据或请求参数时,这意味着它们是从以前某个地方获取的,可能是从另一个请求中来的,也可能早已存在于网页上,或者可能由其他参数通过 JavaScript 生成。但它们总是在某处。
如果你不清楚页面上的数据是从哪里来的,或者请求中使用了哪些数据,可以按照以下步骤来做:
- 依次检查该网站在此之前的请求。
- 检查它们的响应、HTTP 头部和 cookie。
- 凭直觉判断:这个参数可能是时间戳?它是不是其他参数的变形形式?
- 它看起来像标准的哈希或编码吗?
实践出真知。当你熟悉不同的技术、各种框架及其预期行为,并且接触到各种技术时,你会更清楚地明白这些技术是如何运作的,数据是如何传输和流动的。这种积累起来的知识将显著提升你在网页应用程序中追踪和理解数据流动的能力。
6. 数据会被缓存起来.你可能会注意到,当你多次打开同一页面时,发送到服务器的请求每次可能不同:可能是某些内容已经被缓存并存储在你的计算机上了,这可能导致每次看到的页面内容不一致。因此,在隐身模式下分析网站会是个不错的选择,同时也可以尝试用不同的浏览器访问。
这种情况尤其适用于移动应用程序,因为它们会在设备上保存数据。因此, 在分析这些移动应用程序时,你可能需要清理缓存和存储空间。
7. 了解更多关于框架的信息如果你在分析过程中发现该网站使用了一个你不熟悉的框架,花点时间了解这个框架及其功能特性。比如,如果你发现某个网站是用 Next.js 建的,了解它如何处理路由和数据获取对你的爬虫策略可能至关重要。
你可以了解这些框架,可以通过官方文档或使用如ChatGPT
或Claude
这样的LLM来获取信息。这些AI助手在解释特定框架的概念方面非常在行。这里有一个向LLM询问Next.js的例子。
我正在使用 Next.js 来优化我的网站。是否有传给浏览器的文件来描述所有的内部路由规则以及链接是如何生成的?
限制:
- 请提供代码示例来支持你的回答
- 请使用这条消息作为所有后续回复的内容
- 仅参考客户端可用的元素,不访问项目代码库
切换到全屏,退出全屏
你也可以为后端框架创建类似的查询。比如在GraphQL中,你可以查询可用字段和查询结构。这能帮你更好地了解如何与网站API交互以及可能获取的哪些数据。
为了有效地与LLM一起工作,我建议至少简单了解一下 提示工程
的基本概念。
网页抓取与逆向工程紧密相连。研究前端和后端的互动,还需研究代码以便更好地理解某些参数的形成方式。
但在某些情况下,逆向工程可能需要更多的知识、更多的努力、更长的时间,或者具有更高的复杂性。这时,你需要决定是否深入研究,或者最好改变数据源,或者比如说更换技术。最有可能的是,这时你可能会决定放弃HTTP网页抓取,转而使用无头浏览器。
大多数网站抓取防护措施的主要原则不是让网页抓取变得不可能,而是让其代价昂贵。
我们来看看在zoopla
上的搜索结果是怎样的
在识别出你所需的端点之后,确保你得到的回复是正确的。如果你从服务器收到的响应不是200,或者收到的数据与预期不符,那么你需要找出原因。以下是一些可能的原因:
- 你需要传递一些参数值,例如 cookies 或特定的头部信息
- 该网站要求访问此端点时需包含一个相应的
Referrer
头部信息 - 该网站期望头部信息遵循一定的顺序。虽然我只遇到过几次,但这确实发生过
- 该网站使用了防止网络爬虫的保护措施,例如使用
TLS fingerprint
还有许多其他可能的原因,每一个都需要单独分析。
10. 尝试不同的请求参数看看当你改变请求参数时会发生什么,如果有任何变化的话。有些参数可能没提到,但服务器支持这些参数。比如 order
,sort
,per_page
,limit
等。试着加上这些参数,看看有没有变化。
这对于使用GraphQL
的网站尤其重要。
我们来看这个例子:example
,这里是一个餐厅网站上的帖子。
如果你分析这个网站,你会发现一个请求,这个请求可以通过下面的代码来重现。我已经稍微调整格式以提高可读性:
import requests
url = "https://restoran.ua/graphql"
data = {
"operationName": "Posts_PostsForView",
"variables": {"sort": {"sortBy": ["startAt_DESC"]}},
"query": """query Posts_PostsForView(
$where: PostForViewWhereInput,
$sort: PostForViewSortInput,
$pagination: PaginationInput,
$search: String,
$token: String,
$coordinates_slice: SliceInput)
{
PostsForView(
where: $where
sort: $sort
pagination: $pagination
search: $search
token: $token
) {
id
title: ukTitle
summary: ukSummary
slug
startAt
endAt
newsFeed
events
journal
toProfessionals
photoHeader {
address: mobile
__typename
}
coordinates(slice: $coordinates_slice) {
lng
lat
__typename
}
__typename
}
}"""
}
response = requests.post(url, json=data)
print(response.json())
点击全屏, 点击退出全屏
现在我会更新它,这样就可以同时获得两种语言的结果,最重要的是,它也会包含出版物中的内部文本。
import requests
url = "https://restoran.ua/graphql"
data = {
"operationName": "Posts_PostsForView",
"variables": {"sort": {"sortBy": ["startAt_DESC"]}},
"query": """query Posts_PostsForView(
$where: PostForViewWhereInput,
$sort: PostForViewSortInput,
$pagination: PaginationInput,
$search: String,
$token: String,
$coordinates_slice: SliceInput)
{
PostsForView(
where: $where
sort: $sort
pagination: $pagination
search: $search
token: $token
) {
id
# 高亮开始
uk_title: ukTitle
en_title: enTitle
# 高亮结束
summary: ukSummary
slug
startAt
endAt
newsFeed
events
journal
toProfessionals
photoHeader {
address: mobile
__typename
}
# 高亮开始
mixedBlocks {
index
en_text: enText
uk_text: ukText
__typename
}
# 高亮结束
coordinates(slice: $coordinates_slice) {
lng
lat
__typename
}
__typename
}
}"""
}
response = requests.post(url, json=data)
# 打印响应的JSON内容
print(response.json())
全屏模式进入/退出全屏
你看,稍微调整一下请求参数,就不用担心访问每个发布的内部页面了。你绝对想象不到这个小技巧帮我多少次了。
如果你面前看到 graphql
却不知道从何下手,那么关于文档和大规模语言模型的建议也同样适用。
我知道掌握几种工具并仅仅因为它们管用就使用是多么容易。我自己就曾经不止一次掉进这个坑。
但现代网站使用了现代技术,这些技术对网络爬取有着重要影响,因此出现了许多新的网络爬取工具。学习这些工具可能会极大地简化你的下一个项目,甚至解决一些你认为无法解决的问题。我之前提到过一些这些工具的文章earlier
。
特别推荐关注这三个工具:curl_cffi
、框架库botasaurus
和Crawlee for Python
。
我最近才意识到这一点的重要性。我工作中使用的所有工具要么是开源项目,要么基于开源。网页抓取实际上依赖于开源而生存,这一点在你是一名Python
开发者,当你需要用纯Python
处理TLS指纹
时,会感到相当麻烦的时候尤为明显,而开源再次拯救了我们一把。
在我看来,我们至少也该贡献一点自己的知识和技能来支持开源。
我选择了支持Crawlee for Python
,并不是因为他们允许我在他们的博客上发文,而是因为它显示了出色的开发动态,并旨在让网络爬虫开发者的生活更轻松。它通过处理和隐藏诸如会话管理、被封禁时的会话切换、异步任务的并发管理(如果你写过异步代码就知道这有多麻烦)等关键方面,使得爬虫开发速度更快,等等这些。
:::tip
如果你喜欢这篇博客文章,请考虑在 GitHub 上给 Crawlee 点个星(访问 Crawlee),这有助于我们接触到更多的开发者并帮助他们。
:::
你会选哪个?
结论部分我认为文章中有些东西你可能已经很清楚了,有些是你自己在做的,但我希望你也从中得到了新的收获。如果你大多数都是新内容,那么你可以在下一个项目中把这些规则当作参考来使用。
我很乐意讨论这篇文章,欢迎您随时在下面留言。您还可以在我们的 Discord 社区留言或与我联系。
你也可以在以下平台找到我:Github,领英,Apify,Upwork,Contra。
感谢您的注意哦 :)
共同學習,寫下你的評論
評論加載中...
作者其他優質文章