Expedia 是一个受欢迎的网站,人们可以在这里预订航班、酒店等。在在线旅行预订业务的巨头中,Expedia 作为领先平台脱颖而出,为数百万人提供了大量的旅行选择。但您有没有想过如何将这些数据用于您自己的目的,无论是用于研究、分析,还是仅仅为了获得最好的交易?欢迎来到网络抓取的世界!

在本博客中,我们将深入探讨使用 JavaScript 抓取 Expedia 的迷人旅程,解锁充满可能性和机遇的领域。我们将使用 Crawlbase 爬取 API 帮助我们顺利抓取 Expedia。

目录

  1. 为何要抓取 Expedia 的旅行数据?
  2. 了解 Expedia 网站
  • 深入探索 Expedia 的搜索路径
  • Expedia 的前端技术
  • Expedia 搜索结果页面的结构
  • 识别数据点以进行抓取
  1. 设置您的开发环境
  • 安装 NodeJS 和 NPM
  • 设置项目目录
  • 安装所需的库
  • 选择正确的开发 IDE
  • 获取 Crawlbase 爬网 API 的令牌
  1. 抓取 Expedia 搜索结果
  • 构建 Expedia 搜索的 URL
  • 检查 HTML 以获取 CSS 选择器
  • 使用 Crawlbase 抓取 API 访问 HTML 内容
  • 从 Expedia 搜索结果中提取数据
  1. 在 Expedia 中处理分页
  • 了解 Expedia 上的分页
  • 有效处理分页
  1. 存储抓取的数据
  • 以 CSV 格式存储提取的数据
  • 将提取的数据存储在 SQLite 数据库中
  1. 最后的话
  2. 常见问题解答(FAQ)

为何要抓取 Expedia 的旅行数据?

如今,借助 Expedia 等在线平台,计划旅行变得更加便捷和个性化。然而,有如此多的选择和变量,做出明智的决定可能会让人不知所措。这就是从 Expedia 获取旅行数据变得非常有价值的地方。

通过抓取,我们可以从 Expedia 网站收集大量数据,例如航班价格、酒店评论和空房情况。通过分析这些数据,旅行者可以做出更明智的选择,找到最优惠的价格,甚至发现可能不那么明显的隐藏宝石。

对于旅游行业的企业来说,抓取 Expedia 可以提供竞争优势。它提供对市场趋势、竞争对手定价策略和客户偏好的洞察,使企业能够有效地定制其产品和策略。

从本质上讲,抓取 Expedia 的旅行数据使个人旅行者和企业能够更有效地应对旅行计划的复杂性,确保更好的体验和结果。

了解 Expedia 网站

在错综复杂的在线旅游平台网络中,Expedia 是一位杰出的参与者,为用户提供了触手可及的大量旅行选择。为了充分发挥 Expedia 产品的潜力并收集有价值的见解,了解支持其网站的底层结构和技术至关重要。

深入探索 Expedia 的搜索路径

Expedia 提供多种搜索选项,以满足不同的旅行需求。每个搜索路径旨在帮助用户找到特定类型的住宿或活动。以下是一些可用的主要搜索路径的细分:

Expedia 上的可用搜索

Expedia 搜索
  1. 邮轮搜索:此路径专为希望预订游轮的用户而设计。格式示例: https://www.expedia.com/Cruise-Search?querparams...
  2. 汽车搜索:对于那些需要租车的人来说,这条路径简化了搜索过程。格式示例: https://www.expedia.com/carsearch?querparams...
  3. 航班搜索:这条路径的重点是为旅行者寻找最佳的航班选择。例子: https://www.expedia.com/Flight-Search?querparams...
  4. 酒店搜索:专为酒店预订量身定制,这条路径是我们本例的重点。格式示例: https://www.expedia.com/Hotel-Search?querparams...
  5. 要做的事:对于寻求活动和体验的旅行者来说,这条路线提供了一系列精选的选择。格式示例: https://www.expedia.com/things-to-do/search?querparams...

示例:Expedia 上的酒店搜索

在本博客中,我们将深入研究 Expedia 的酒店搜索功能。让我们仔细看看酒店搜索的示例 URL:

1
HTTPS://www.expedia.com/Hotel-Search?adults=2&rooms=1&destination=Dubai%2C%20Dubai%2C%20United%20Arab%20Emirates&startDate=2023-12-26&endDate=2023-12-30

在此 URL 中,您可以看到有助于定制搜索的各种参数:

  • adults=2:指定成人的数量。
  • rooms=1:表示需要的房间数量。
  • destination=Dubai%2C%20Dubai%2C%20United%20Arab%20Emirates:定义目的地,在本例中为阿拉伯联合酋长国迪拜。
  • startDate=2023-12-26:设置住宿的开始日期。
  • endDate=2023-12-30:设置住宿的结束日期。

了解这些搜索路径和参数对于有效抓取至关重要,因为它使我们能够针对特定数据并相应地定制我们的抓取方法。

Expedia 的前端技术

Expedia 采用了多种前端技术来提供用户友好的界面和动态功能:

  1. HTML/CSS:构建和设计网页内容的基础语言,确保视觉吸引力和响应式设计。
  2. JavaScript:支持交互元素和动态内容加载,增强用户体验和交互性。
  3. AJAX:促进无缝数据检索和更新,无需重新加载整页,从而带来更流畅的浏览体验。

Expedia 搜索结果页面的结构

Expedia 的搜索结果页面经过精心设计,旨在为用户提供无缝的预订体验。搜索页面的核心通常包含以下元素:

Expedia 搜索页面
  1. 搜索栏:核心功能允许用户输入他们的旅行偏好,包括目的地、日期和其他相关详细信息。
  2. 过滤器和排序选项:这些工具位于搜索结果旁边,使用户能够根据价格、持续时间、航空公司等各种条件优化搜索。
  3. 搜索结果:此部分突出显示,展示符合用户条件的可用航班、酒店或套餐,通常附有相关详细信息和图像。
  4. 附加信息:补充部分可能包括旅行指南、推荐和客户评论,为用户提供其选择的全面视图。

识别数据点以进行抓取

要从 Expedia 中提取有意义的数据,识别并定位与您的目标相关的特定数据点至关重要。抓取的常见数据点包括:

  1. 航班详情:包括航空公司、航班号、出发和到达时间、时长和价格。
  2. 酒店资讯:例如酒店名称、位置、设施、评级和价格。
  3. 用户评论和评分:提供有关航班、酒店或套餐的质量和体验的见解。
  4. 额外费用和税费:提供与预订相关的任何额外费用的透明度。

通过更深入地了解 Expedia 的搜索路径、掌握其底层技术、掌握其网站架构并查明基本数据元素,您将做好充分准备,踏上成功的抓取之旅,提取有价值的见解并优化您的旅行工作。

设置您的开发环境

在您开始使用 JavaScript 和 Crawlbase Crawling API 进行网络爬行之前,必须准备好您的开发环境。 本节提供简洁而详细的指南,帮助您设置无缝电子商务网站爬行所需的工具和库。

安装 NodeJS 和 NPM

NodeJS 和 NPM(节点包管理器)是现代 JavaScript 开发的支柱。 它们允许您在 Web 浏览器的范围之外执行 JavaScript 代码并轻松管理依赖项。 这是一个简单的安装指南:

  1. 的NodeJS: 访问官方 NodeJS 网站 并下载为您的操作系统量身定制的最新 LTS(长期支持)版本。按照提供的特定于平台的说明执行安装。
  2. NPM:NPM 与 NodeJS 捆绑在一起。安装 NodeJS 后,您将自动拥有 NPM 供您使用。

要确认安装成功,请打开终端或命令提示符并运行以下命令:

1
2
节点 - 版本
npm --版本

这些命令将显示已安装的 NodeJS 和 NPM 版本,确保安装顺利。

设置项目目录

首先,使用以下命令创建一个目录 mkdir 命令。它被称为 ecommerce crawling 为了本教程的目的,您可以将名称替换为您选择的名称之一:

1
MKDIR expedia\ 抓取

接下来,使用以下命令切换到新创建的目录 cd 命令:

1
cd expedia\ 抓取/

使用以下命令将项目目录初始化为 npm 包 npm 命令:

1
npm 初始化 --y

该命令创建一个 package.json 文件,其中包含项目的重要元数据。这 --y 选项指示 npm 接受所有默认值。

运行命令后,屏幕上将显示以下输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
 到/家/哈桑/桌面版/电子商务爬行/包。JSON:

{
“名称”: “expedia 抓取”,
“版”: “1.0.0”,
“说明”: "",
“主要”: “ index.js”,
“脚本”{
“测试”: “回显\”错误:未指定测试\“ &&退出1”
},
“关键词”:[],
“作者”: "",
“执照”: “走”
}

在项目目录中,创建一个名为 expedia-scraping.js 的新文件。这是您放置抓取代码的位置。

1
触摸 expedia-scraping.js

安装所需的库

为了熟练地进行网络爬行和 API 交互,请使用 NPM 为您的项目配备以下 JavaScript 库:

1
2
# 安装所需的库
npm 安装cheeriocrawlbasesqlite3csv-writer

以下是这些重要库的简要概述:

  • 切里奥:作为一个敏捷且高性能的库,Cheerio 旨在高效解析 HTML 和 XML 文档。它在轻松地从网页中提取有价值的数据方面发挥着关键作用。
  • 爬虫库:Crawlbase 简化了与 Crawlbase Crawling API 的交互,简化了网站抓取和数据提取的过程。
  • SQLite3:SQLite3 是一个独立、无服务器、零配置的 SQL 数据库引擎。它将作为您的存储库,用于存储爬行过程中收集的大量数据。
  • csv 编写器:它简化了将数据写入 CSV 文件的过程,使您可以轻松创建结构化数据文件以在应用程序中进行存储或进一步分析。它提供了一个直观的 API,用于使用最少的代码定义标头并将记录写入 CSV 文件。

选择正确的开发 IDE

选择正确的集成开发环境 (IDE) 可以显着提高生产力。 虽然您可以在简单的文本编辑器中编写 JavaScript 代码,但使用专用 IDE 可以提供代码完成、调试工具和版本控制集成等功能。

用于 JavaScript 开发的一些流行 IDE 包括:

  • Visual Studio 代码(VS 代码):VS Code 是 Microsoft 开发的免费开源代码编辑器。它拥有一个充满活力的社区,为 JavaScript 开发提供了广泛的扩展。
  • 网络风暴:WebStorm 是 JetBrains 的一款商业 IDE,以其智能编码帮助和强大的 JavaScript 支持而闻名。
  • 崇高的文字:Sublime Text 是一款轻量级、可自定义的文本编辑器,因其速度和可扩展性而受到开发人员的欢迎。

选择适合您的偏好和工作流程的 IDE。

获取 Crawlbase 爬网 API 的令牌

要访问 Crawlbase 爬网 API,您需要访问令牌。 要获取令牌,您首先需要在 Crawlbase 上创建一个帐户。 现在,让我们为您设置一个 Crawlbase 帐户。 按着这些次序:

  1. 访问 Crawlbase 网站:打开网络浏览器并导航至 Crawlbase 注册页面 开始注册过程。
  2. 提供您的详细信息:系统会要求您提供电子邮件地址并为您的 Crawlbase 帐户创建密码。 填写所需信息。
  3. 企业验证:提交详细信息后,您可能需要验证您的电子邮件地址。 检查您的收件箱中是否有来自 Crawlbase 的验证电子邮件,然后按照提供的说明进行操作。
  4. 登录 :验证您的帐户后,返回 Crawlbase 网站并使用您新创建的凭据登录。
  5. 访问您的 API 令牌:您需要 API 令牌才能使用抓取 API。您可以在此找到您的代币 链接.

Crawlbase 提供两种类型的令牌:用于静态网站页面的普通令牌 (TCP) 和用于动态或 JavaScript 呈现的网站页面的 JavaScript 令牌 (JS)。像Expedia这样的网站,你需要JS Token。您可以阅读更多内容 点击此处.

准备好 NodeJS、NPM、基本库和 API 令牌后,您现在就可以使用 JavaScript 和 Crawlbase 抓取 API 深入研究 Expedia 抓取了。在以下部分中,我们将逐步指导您完成该过程。

抓取 Expedia 搜索结果

Expedia 上提供的海量旅行信息和选项对于旅行者和分析师来说都是一个宝库。通过抓取 Expedia 的搜索结果,人们可以获得丰富的数据见解,可用于各种目的。在本部分中,我们将引导您逐步完成抓取 Expedia 搜索结果的细致过程。

每个在线平台都在结构化框架上运行,Expedia 也不例外。要发起搜索或抓取数据,需要构建封装所需搜索参数的适当 URL。

例如,如果您有兴趣探索巴黎的酒店选择以度过周末,您的网址可能如下所示:

1
HTTPS://www.expedia.com/Hotel-Search?adults=2&rooms=1&destination=Paris&startDate=2023-12-26&endDate=2023-12-30

分解组件:

  • 基本网址: https://www.expedia.com/Hotel-Search
  • 参数:
    • adults=2:指定成人的数量。
    • rooms=1:表示需要的房间数量。
    • destination=Paris:以 URL 编码格式指定目标。
    • startDate=2023-12-26:设置住宿的开始日期。
    • endDate=2023-12-30:设置住宿的结束日期。

使用正确的参数构建此类 URL 是从 Expedia 抓取准确且相关的数据的基础。

使用 Crawlbase 抓取 API 访问 HTML 内容

一旦精心设计了必要的 URL,接下来的任务就是提取网页的 HTML 内容。 Crawlbase 爬行 API 成为这一努力中的一项工具资产。下面描述了促进此操作的结构化方法:

  1. API 配置:初始化Crawlbase Crawling API,集成您的特定API令牌。
  2. 请求执行:使用API​​从指定的URL获取HTML内容。为了进一步优化您的抓取过程,必须了解 参数 您可以使用 Crawlbase 爬行 API:
  • ajax_等待:一个布尔参数,指示 API 是否应该等待 AJAX 内容加载。将其设置为 true 可确保在捕获 HTML 之前完全呈现异步内容。
  • 页面等待:指定 API 在页面加载后捕获 HTML 之前应等待的持续时间(以毫秒为单位)。当内容需要较长时间才能完全交互或处理具有复杂加载顺序的网站时,调整此值会有所帮助。

下面是一个详细的示例,说明了这些参数的集成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
常量 { 抓取API } = 要求('crawlbase');

// 插入您的 Crawlbase JS 令牌代替“YOUR_CRAWLBASE_JS_TOKEN”
常量 接口= 抓取API({ 象征: 'YOUR_CRAWLBASE_JS_TOKEN' });

常量 选项= {
ajax_等待: true,
页面等待: 5000,
};

常量 expediaURL =
'https://www.expedia.com/Hotel-Search?adults=2&rooms=1&destination=Paris&startDate=2023-12-26&endDate=2023-12-30';

异步 功能 fetchExpediaHTML(网址){
常量 响应 = 等待 蜜蜂。得到(网址,选项);
回报 响应。身体;
}

fetchExpediaHTML(expediaURL)。然后((响应) => {
领事.日志(回复);
});

执行指令:

  • 将上述代码复制并粘贴到 expedia-scraping.js 文件中。
  • 要执行该脚本,请导航到终端中的项目目录并运行:
1
节点 expedia-scraping.js

这将在您的终端中显示检索到的 HTML。

输出 HTML 预览

检查 HTML 以获取 CSS 选择器

通过从属性页获取 HTML 内容,下一步是分析其结构并查明定价数据的位置。 这项任务正是 Web 开发工具和浏览器开发工具来拯救我们的地方。 让我们概述一下如何检查 HTML 结构并挖掘那些宝贵的 CSS 选择器:

Expedia 搜索页面检查
  1. 前往 Expedia 网站:在您选择的浏览器中打开 Expedia SERP URL。
  2. 使用右键单击并检查:右键单击要从中获取信息的页面元素。从出现的菜单中选择“检查”或“检查元素”。这将在您的浏览器中打开开发人员工具。
  3. 查找 HTML 代码:在开发者工具中查找HTML源代码。将鼠标移动到代码的不同部分,网页上相应的区域就会亮起。
  4. 获取 CSS 选择器:要获取特定元素的 CSS 选择器,请在开发人员工具中右键单击该元素,然后选择“复制”>“复制选择器”。这会将 CSS 选择器复制到剪贴板上,您可以将其用于网页抓取。

一旦有了这些选择器,您就可以继续构建数据抓取器以有效地提取所需的信息。

从 Expedia 搜索结果中提取数据

成功检索 HTML 内容后,下一步是仔细提取基本数据元素。对于此任务,我们利用解析工具的功能,其中 JavaScript 中的 Cheerio 库是我们的首选。

以下是该过程的改进方法:

  1. HTML解析:将获取的 HTML 内容集成到 Cheerio 等解析框架中,从而实现文档对象模型 (DOM) 的无缝导航。
  2. 精确的数据提取:策略性地部署 CSS 选择器,以从 HTML 结构中隔离和提取关键数据片段。这包括关键指标,例如酒店名称、每晚价格、累计价格、评级和用户评论计数。
  3. 数据结构化:随着提取的展开,有条不紊地将收集到的数据组织成结构化格式,无论是 JSON 还是 CSV。这确保了清晰度、可访问性,并有利于后续数据分析或归档。

为了与我们之前的脚本编写工作保持一致,修订后的代码部分保留:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
常量 { 抓取API } = 要求('crawlbase');
常量 欢呼= 要求('cheerio');

// 初始化Crawlbase API
常量 api令牌 = 'YOUR_CRAWLBASE_JS_TOKEN'; // 在此处插入您的 Crawlbase JS 令牌
常量 接口= 抓取API({ 象征: apiToken });

// API 选项
常量 选项= {
ajax_等待: true,
页面等待: 5000,
};

// 目标 Expedia URL
常量 expediaURL =
'https://www.expedia.com/Hotel-Search?adults=2&rooms=1&destination=Paris&startDate=2023-12-26&endDate=2023-12-30';

// 从 Expedia 获取 HTML 内容
异步 功能 fetchExpediaHTML(网址){
常量 响应 = 等待 蜜蜂。得到(网址,选项);
回报 响应。身体;
}

// 从 HTML 内容中提取酒店详细信息
功能 提取酒店详情(html内容){
常量 $ = 快乐。加载(html内容);
常量 酒店=[];

$('div[data-stid="property-listing-results"] .uitk-card').((索引、元素) => {
常量 酒店={
姓名:$(元素)。发现('.uitk-card-content-section h3.uitk-heading').文本()
每晚价格:$(元素)
.发现(
'.uitk-card-content-section div[data-test-id="price-summary"] > div > div:first-child > div span div.uitk-text'
)
.文本()
总价:$(元素)
.发现('.uitk-card-content-section div[data-test-id="price-summary"] > div > div:nth-child(2) div.uitk-text')
.文本()
等级:$(元素)
.发现('.uitk-card-content-section .uitk-layout-flex span.uitk-badge span.uitk-badge-base-text')
.文本()
评论:$(元素)
.发现(
'.uitk-card-content-section div.uitk-layout-grid div:first-child > div.uitk-layout-flex > div:nth-child(2) > div:nth-child(2) > div:最后一个子级 > span > div.uitk-text'
)
.文本()
};
酒店。(酒店);
});

回报 酒店;
}

// 执行抓取的主函数
异步 功能 (){
常量 html内容= 等待 fetchExpediaHTML(expediaURL);
常量 酒店数据 = 提取酒店详情(html内容);

领事.日志(酒店数据); // 显示提取的酒店详细信息
}

// 执行主函数
()。捕捉((错误) => {
领事.错误(“发生错误:”, 错误);
});

使用 CrawlingAPI 该脚本从“crawlbase”库中获取预定义 Expedia URL 的 HTML 内容。然后使用以下内容解析该内容 cheerio 库,一个类似于 jQuery 的服务器端实现,用于提取基本的酒店详细信息,如名称、价格、评级和评论。处理后,脚本将提取的数据输出到控制台。值得注意的是,错误处理被纳入以管理抓取操作期间的任何潜在问题。

运行上面的代码将给出如下输出:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
[
{
姓名: “巴黎吕埃马尔迈松 OKKO 酒店”,
每晚价格: '$118',
总价: '$542 全部的',
等级: '9.0',
评论: “精彩286条评论”
},
{
姓名: “勒维克大酒店”,
每晚价格: '$174',
总价: '$782 全部的',
等级: '8.4',
评论: '1,004 评论'
},
{
姓名: '巴黎星辰凯悦酒店',
每晚价格: '$250',
总价: '$1,129 全部的',
等级: '8.6',
评论: '1,002 评论'
},
{
姓名: “里维埃拉爱丽舍酒店”,
每晚价格: '$98',
总价: '$449 全部的',
等级: '7.0',
评论: '469 评论'
},
{
姓名: “巴黎歌剧院公民”,
每晚价格: '$192',
总价: '$871 全部的',
等级: '9.6',
评论: '76 评论'
},
{
姓名: “都灵大酒店”,
每晚价格: '$98',
总价: '$448 全部的',
等级: '7.6',
评论: '1,002 评论'
},
... 93 更多项目
]

在 Expedia 中处理分页

像 Expedia 这样的抓取平台经常通过一系列页面(通常称为分页)来呈现搜索结果。为了确保我们捕获所有所需的数据,我们需要在抓取过程中考虑此分页。下面,我们将探讨如何在使用 Crawlbase 库抓取 Expedia 时有效地处理分页。

了解 Expedia 上的分页

Expedia 上的分页旨在通过以可管理的块形式显示搜索结果来简化用户体验。当您滚动或浏览这些结果时,平台会动态加载其他列表。

Expedia 中的分页

要以编程方式提取所有列表,有必要与“显示更多”按钮或其等效按钮进行交互,直到不再加载更多结果。

有效处理分页

为了有效处理分页,Crawlbase Crawling API 提供了 css_click_selector 范围。此参数允许我们以编程方式单击页面上的元素,触发附加内容的加载。

使用 JavaScript 令牌时, css_click_selector 参数需要一个有效的 CSS 选择器,可以是 ID(例如, #some-button),一个类(例如, .some-other-button),或一个属性(例如, [data-tab-item="tab1"])。确保 CSS 选择器正确编码以避免任何差异至关重要。

让我们将其合并到我们现有的脚本中:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
常量 { 抓取API } = 要求('crawlbase');
常量 欢呼= 要求('cheerio');

// 初始化Crawlbase API
常量 api令牌 = 'YOUR_CRAWLBASE_JS_TOKEN'; // 在此处插入您的 Crawlbase JS 令牌
常量 接口= 抓取API({ 象征: apiToken });

// API 选项
常量 选项= {
ajax_等待: true,
页面等待: 10000,
css_click_selector: 编码URI组件('按钮[data-stid =“显示更多结果”]'),
};

// 目标 Expedia URL
常量 expediaURL =
'https://www.expedia.com/Hotel-Search?adults=2&rooms=1&destination=Paris&startDate=2023-12-26&endDate=2023-12-30';

// 从 Expedia 获取 HTML 内容
异步 功能 fetchExpediaHTML(网址){
常量 响应 = 等待 蜜蜂。得到(网址,选项);
if (回复。 && 回复。.电脑状态 === 200){
回报 响应。身体;
}
回报 ;
}

// 从 HTML 内容中提取酒店详细信息
功能 提取酒店详情(html内容){
常量 $ = 快乐。加载(html内容);
常量 酒店=[];

$('div[data-stid="property-listing-results"] .uitk-card').((索引、元素) => {
常量 酒店={
姓名:$(元素)。发现('.uitk-card-content-section h3.uitk-heading').文本()
每晚价格:$(元素)
.发现(
'.uitk-card-content-section div[data-test-id="price-summary"] > div > div:first-child > div span div.uitk-text'
)
.文本()
总价:$(元素)
.发现('.uitk-card-content-section div[data-test-id="price-summary"] > div > div:nth-child(2) div.uitk-text')
.文本()
等级:$(元素)
.发现('.uitk-card-content-section .uitk-layout-flex span.uitk-badge span.uitk-badge-base-text')
.文本()
评论:$(元素)
.发现(
'.uitk-card-content-section div.uitk-layout-grid div:first-child > div.uitk-layout-flex > div:nth-child(2) > div:nth-child(2) > div:最后一个子级 > span > div.uitk-text'
)
.文本()
};
酒店。(酒店);
});

回报 酒店;
}

// 执行抓取的主函数
异步 功能 (){
常量 html内容= 等待 fetchExpediaHTML(expediaURL);
if (html内容){
常量 酒店数据 = 提取酒店详情(html内容);
领事.日志(酒店数据);
} 其他 {
领事.日志(“获取 HTML 时出现问题。”);
}
}

// 执行主函数
()。捕捉((错误) => {
领事.错误(“发生错误:”, 错误);
});

在输出中,您会注意到结果比上次运行的结果更多。

存储抓取的数据

从 Expedia 等平台成功提取数据后,必须拥有一个强大的数据存储系统。这确保了数据仍然可访问、组织良好,并且可以在未来有效地用于各种目的。让我们探索两种存储抓取数据的系统方法:使用 CSV 文件和利用 SQLite 数据库。

以 CSV 格式存储提取的数据

CSV(逗号分隔值)由于其简单性和与各种软件的兼容性而成为数据交换的标准。通过以 CSV 格式保存抓取的数据,您可以确保其广泛的可用性。

您可以按如下方式修改现有脚本来集成此更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
常量 { 抓取API } = 要求('crawlbase');
常量 欢呼= 要求('cheerio');
常量 创建CsvWriter = 要求('csv-writer').创建ObjectCsvWriter;

// 初始化Crawlbase API
常量 api令牌 = 'YOUR_CRAWLBASE_JS_TOKEN'; // 在此处插入您的 Crawlbase JS 令牌
常量 接口= 抓取API({ 象征: apiToken });

// API 选项
常量 选项= {
ajax_等待: true,
页面等待: 8000,
css_click_selector: 编码URI组件('按钮[data-stid =“显示更多结果”]'),
};

// 目标 Expedia URL
常量 expediaURL =
'https://www.expedia.com/Hotel-Search?adults=2&rooms=1&destination=Paris&startDate=2023-12-26&endDate=2023-12-30';

// 从 Expedia 获取 HTML 内容
异步 功能 fetchExpediaHTML(网址){
常量 响应 = 等待 蜜蜂。得到(网址,选项);
if (回复。 && 回复。.电脑状态 === '200'){
回报 响应。身体;
}
回报 ;
}

// 从 HTML 内容中提取酒店详细信息
功能 提取酒店详情(html内容){
常量 $ = 快乐。加载(html内容);
常量 酒店=[];

$('div[data-stid="property-listing-results"] .uitk-card').((索引、元素) => {
常量 酒店={
姓名:$(元素)。发现('.uitk-card-content-section h3.uitk-heading').文本()
每晚价格:$(元素)
.发现(
'.uitk-card-content-section div[data-test-id="price-summary"] > div > div:first-child > div span div.uitk-text'
)
.文本()
总价:$(元素)
.发现('.uitk-card-content-section div[data-test-id="price-summary"] > div > div:nth-child(2) div.uitk-text')
.文本()
等级:$(元素)
.发现('.uitk-card-content-section .uitk-layout-flex span.uitk-badge span.uitk-badge-base-text')
.文本()
评论:$(元素)
.发现(
'.uitk-card-content-section div.uitk-layout-grid div:first-child > div.uitk-layout-flex > div:nth-child(2) > div:nth-child(2) > div:最后一个子级 > span > div.uitk-text'
)
.文本()
};
酒店。(酒店);
});

回报 酒店;
}

// 将数据保存到CSV文件中
功能 保存为CSV(data){
常量 csvWriter = 创建CsvWriter({
: “酒店.csv”,
[
{ id: “名称”, 标题: '姓名' },
{ id: '每晚价格', 标题: “每晚价格” },
{ id: '总价', 标题: “总价” },
{ id: '评分', 标题: '评分' },
{ id: ‘评论’, 标题: “评论” },
],
});

csvWriter。写记录(数据)。然后(() => 领事.日志(“数据已成功保存到 CSV”));
}

// 执行抓取的主函数
异步 功能 (){
常量 html内容= 等待 fetchExpediaHTML(expediaURL);
if (html内容){
常量 酒店数据 = 提取酒店详情(html内容);
保存为CSV(酒店数据);
} 其他 {
领事.日志(“获取 HTML 时出现问题。”);
}
}

// 执行主函数
()。捕捉((错误) => {
领事.错误(“发生错误:”, 错误);
});

saveToCSV 函数利用 createCsvWriter 模块来定义 CSV 写入器配置。此配置指定数据应写入名为的文件 hotels.csv,它提供了 CSV 的结构,其中包含“名称”、“每晚价格”、“总价格”、“评级”和“评论”等标题。提取的酒店数据(之前组织成对象数组)随后将写入此 CSV 文件。

hotels.csv 预习:

hotels.csv 预览

将提取的数据存储在 SQLite 数据库中

SQLite 为数据存储提供了可靠的无服务器解决方案。通过使用 SQLite 数据库,您可以受益于结构化查询功能,确保数据完整性和高效检索。

您可以按如下方式修改脚本来集成此更新。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
常量 { 抓取API } = 要求('crawlbase');
常量 欢呼= 要求('cheerio');
常量 sqlite3= 要求('sqlite3').详细();

// 初始化Crawlbase API
常量 api令牌 = 'YOUR_CRAWLBASE_JS_TOKEN'; // 在此处插入您的 Crawlbase JS 令牌
常量 接口= 抓取API({ 象征: apiToken });

// API 选项
常量 选项= {
ajax_等待: true,
页面等待: 8000,
css_click_selector: 编码URI组件('按钮[data-stid =“显示更多结果”]'),
};

// 目标 Expedia URL
常量 expediaURL =
'https://www.expedia.com/Hotel-Search?adults=2&rooms=1&destination=Paris&startDate=2023-12-26&endDate=2023-12-30';

// 从 Expedia 获取 HTML 内容
异步 功能 fetchExpediaHTML(网址){
常量 响应 = 等待 蜜蜂。得到(网址,选项);
if (回复。 && 回复。.电脑状态 === '200'){
回报 响应。身体;
}
回报 ;
}

// 从 HTML 内容中提取酒店详细信息
功能 提取酒店详情(html内容){
常量 $ = 快乐。加载(html内容);
常量 酒店=[];

$('div[data-stid="property-listing-results"] .uitk-card').((索引、元素) => {
常量 酒店={
姓名:$(元素)。发现('.uitk-card-content-section h3.uitk-heading').文本()
每晚价格:$(元素)
.发现(
'.uitk-card-content-section div[data-test-id="price-summary"] > div > div:first-child > div span div.uitk-text'
)
.文本()
总价:$(元素)
.发现('.uitk-card-content-section div[data-test-id="price-summary"] > div > div:nth-child(2) div.uitk-text')
.文本()
等级:$(元素)
.发现('.uitk-card-content-section .uitk-layout-flex span.uitk-badge span.uitk-badge-base-text')
.文本()
评论:$(元素)
.发现(
'.uitk-card-content-section div.uitk-layout-grid div:first-child > div.uitk-layout-flex > div:nth-child(2) > div:nth-child(2) > div:最后一个子级 > span > div.uitk-text'
)
.文本()
};
酒店。(酒店);
});

回报 酒店;
}

// 将数据保存到SQLite中
功能 保存到SQLite(data){
常量 分贝= sqlite3。数据库('酒店.db');

// 确保表存在
D b。运行(`如果不存在酒店则创建表 (
id 整数主键,
名称文本,
每晚真实价格,
总价格真实,
评级真实,
评论 整数
)`);

// 插入数据
数据。每次((饭店) => {
D b。运行(`插入酒店(名称、每晚价格、总价格、评分、评论)值 (?, ?, ?, ?, ?)`[
酒店。姓名,
酒店。每晚价格,
酒店。总价,
酒店。等级,
酒店。评论,
])?
});

D b。关闭((犯错) => {
if (呃) {
回报 领事.错误(呃。message);
}
领事.日志('数据已成功保存到SQLite数据库');
});
}

// 执行抓取的主函数
异步 功能 (){
常量 html内容= 等待 fetchExpediaHTML(expediaURL);
if (html内容){
常量 酒店数据 = 提取酒店详情(html内容);
保存到SQLite(酒店数据);
} 其他 {
领事.日志(“获取 HTML 时出现问题。”);
}
}

// 执行主函数
()。捕捉((错误) => {
领事.错误(“发生错误:”, 错误);
});

saveToSQLite 函数旨在将酒店数据存储到名为hotels.db 的SQLite 数据库中。调用时,它使用以下命令建立与 SQLite 数据库的连接 sqlite3 模块。在插入任何数据之前,该函数确保名为 hotels 存在于数据库中;如果没有,它会创建此表,其中包含 ID(作为主键)、酒店名称、每晚价格、总价、评级和评论数量的列。随后,该函数迭代传递给它的每个酒店对象,执行插入查询以将酒店的详细信息添加到 hotels 桌子。插入所有数据后,该函数将关闭数据库连接,确保数据安全地保存在 SQLite 数据库中。

hotels 表格预览:

酒店表格预览

最后的话

恭喜!您直接从网页获取原始数据,并将其转换为 JSON 文件中的结构化数据。现在您已经了解如何在 JS 中构建 Expedia 抓取工具的每一步了!

本指南为您提供了使用 JS 和 Crawlbase 抓取 API 轻松抓取 Expedia 搜索结果的基本知识和工具。继续阅读我们的博客以获取更多此类教程。下面给出了一些链接:

如何抓取 Booking.com

并且,如果您想浏览其他 JavaScript 项目,我们建议您检查以下链接:

使用 JavaScript 掌握电子商务网络爬行
如何使用 JavaScript 抓取 G2
如何使用 JavaScript 抓取 eBay

在此之前,如果您遇到任何问题,请随时联系 Crawlbase 支持团队。您在网络抓取方面的成功是我们的首要任务,我们期待在您的抓取之旅中为您提供支持。

常见问题解答

网络抓取,尤其是来自 Expedia 等大型商业平台的抓取,存在于法律的灰色地带。虽然某些司法管辖区和服务条款明确禁止抓取,但其他司法管辖区和服务条款可能没有明确的指导方针。彻底查看 Expedia 的服务条款或咨询熟悉您所在地区互联网法律的法律专家至关重要。请记住,即使没有明确禁止抓取,也必须实行道德抓取,以确保您不会违反任何条款或对 Expedia 的服务器造成过度压力。此外,始终尊重 robots.txt 文件,网站经常使用这些文件来指示可以或不能抓取网站的哪些部分。

为什么使用 Cheerio 这样的 JavaScript 库来进行抓取?

Cheerio 等 JavaScript 库是网页抓取任务的宝贵工具。与执行 JavaScript 来渲染页面的传统浏览器不同,cheerio 在服务器端运行,提供模拟 DOM 环境。这种服务器端方法消除了渲染整个网页的需要,从而加快了数据提取过程。开发人员可以使用熟悉的类似 jQuery 的语法来导航和提取特定的 HTML 元素,从而简化复杂的抓取任务并优化性能。

抓取 Expedia 时如何处理速率限制或 IP 禁令?

包括 Expedia 在内的网站采用速率限制或 IP 禁令等各种机制来阻止和管理攻击性或未经授权的抓取活动。如果您发现延迟或被阻止,则表明您的抓取活动可能过于激进。为了应对这些挑战:

  • 实施延误:在抓取请求之间引入随机或系统延迟,以模仿人类行为并减少服务器上的负载。
  • 使用代理:通过代理池轮流屏蔽您的 IP 地址并分发请求,使网站更难跟踪和阻止您的抓取活动。
  • 速率限制工具:考虑集成旨在管理和遵守速率限制的中间件或工具,根据服务器响应动态调整抓取速度。

此外,为了获得简化且无忧的体验,Crawlbase 等平台提供了专用的爬网 API。利用此类服务​​可以进一步自动化和优化您的抓取工作,从而在管理潜在限制方面提供更复杂的层。

我应该如何处理从 Expedia 抓取的数据?

抓取数据的道德和合法使用至关重要。在使用抓取的数据之前:

  • 使用目的: 明确你的意图。如果您正在分析数据以获取个人见解或学术研究,请确保您的活动符合网站的服务条款。
  • 商业用途:如果您计划将数据用于商业用途,请务必获得 Expedia 或相应网站的明确许可。未经同意出售或重新利用抓取的数据可能会导致法律后果并损害您在行业中的声誉。
  • 数据隐私:始终优先考虑数据隐私。确保安全处理从 Expedia 或其他来源提取的任何个人或敏感信息,尊重个人隐私权和法规。