如何使用 Elixir 开始网络抓取的终极指南

Suciu Dan,2022 年 10 月 18 日

导言

网络搜刮是从论坛、社交媒体网站、新闻网站、电子商务平台等公开网站中提取数据的过程。本文将介绍如何在 Elixir 中创建 Web scraper,让您先睹为快。

如果您还不清楚网络搜刮的定义,那么让我们把从网站上保存图片视为手动网络搜刮。如果要手工保存网站上的所有图片,根据网站的复杂程度,可能需要几个小时甚至几天的时间。 

您可以通过构建网络搜刮器来自动完成这一过程。

也许你想知道网络刮刀有哪些用途。以下是常见的几种情况:

新闻追踪

您可以从最喜欢的财经新闻网站上获取最新消息,运行情绪分析算法,并在市场开始和变动前几分钟就知道该投资什么。

社交媒体洞察

您可以从社交媒体页面上抓取评论,分析用户在谈论什么以及他们对产品或服务的感受。

价格监控

如果你热衷于收集游戏机和视频游戏,但又不想花大价钱购买最新的 PS5,你可以制作一个网络搜索器,检索 eBay 上的列表,并在廉价游戏机上市时向你发送通知。

机器学习培训

如果你想创建一个能识别任何图片中猫的品种的移动应用程序,你需要大量的训练数据;与其手动保存成百上千张猫的图片来训练模型,你可以使用网络搜刮工具来自动完成。

我们将使用 Elixir 构建网络刮擦程序,Elixir 是一种基于 Erlang 的编程语言,由 Ruby on Rails 团队核心成员何塞-瓦利姆(José Valim)创建。该编程语言借鉴了 Ruby 语法的简洁性,并将其与 Erlang 构建低延迟、分布式和容错系统的能力相结合。

要求

在编写第一行代码之前,请确保您的计算机上安装了 Elixir。下载适用于您操作系统的安装程序,并按照安装页面的说明进行操作。 

在安装过程中,你会发现 Erlang 编程语言也是必需的。请记住,Elixir 在 Erlang 虚拟机中运行,因此两者都需要。

开始

在本文中,您将学习如何在 Elixir 中创建一个网络搜刮器,从 eBay 搜刮产品的 PS5 列表,并将提取的数据(名称、url、价格)存储到本地。

检查目标

是时候检查 eBay 页面上的搜索结果并收集一些选择器了。

访问 ebay.com,在 "搜索 "输入框中输入 PS5 并点击 "搜索 "按钮。加载搜索结果页面后,打开浏览器中的检查工具(右键单击页面上的任意位置并选择检查)。

您需要收集以下选择器:

  • 产品清单 项目
  • 产品网址
  • 产品名称
  • 产品价格

使用选择元素工具,搜索产品项目列表 (ul) 和产品项目 (li):

博客图片

利用这两个元素,就可以提取出爬虫提取数据所需的类:

  • .srp-results .s-item 产品列表元素 (ul) 的子元素
  • .s-item__title span 产品标题
  • .s-item__link 产品链接
  • .s-item__price 产品价格

创建项目

让我们使用 mix 命令创建一个 Elixir 项目:

mix new elixir_spider --sup

--sup标志会生成一个包含监督树的 OTP 应用程序骨架,这是管理多个并发进程(如爬虫)的应用程序所需的功能。

创建临时文件夹

将当前目录更改为项目根目录:

cd elixir_spider

创建临时目录:

mkdir temp

我们使用该目录来存储搜刮到的项目。

添加依赖项

创建项目后,需要添加两个依赖项:

  • Crawly是一个用于抓取网站和提取结构化数据的应用框架
  • Floki是一款 HTML 解析器,可使用 CSS 选择器搜索节点

打开 mix.exs 文件,在 deps 块中添加依赖项:

defp deps do
[
{:crawly, "~> 0.14.0"},
{:floki, "~> 0.33.1"}
]
end

运行此命令获取依赖项:

mix deps.get

创建配置

创建 config/config.exs 文件并粘贴此配置:

import Config

config :crawly,
closespider_timeout: 10,
concurrent_requests_per_domain: 8,
closespider_itemcount: 100,

middlewares: [
Crawly.Middlewares.DomainFilter,
Crawly.Middlewares.UniqueRequest,
{Crawly.Middlewares.UserAgent, user_agents: ["Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:105.0) Gecko/20100101 Firefox/105.0"]}
],
pipelines: [
{Crawly.Pipelines.Validate, fields: [:url, :title, :price]},
{Crawly.Pipelines.DuplicatesFilter, item_id: :title},
Crawly.Pipelines.JSONEncoder,
{Crawly.Pipelines.WriteToFile, extension: "jl", folder: "./temp"}
]

一般选项

让我们对每处房产进行一番了解:

  • closeespider_timeout:整数,蜘蛛保持打开状态的最长秒数
  • concurrent_requests_per_domain(每个域的并发请求数):每个刮擦域的最大请求数
  • closespider_itemcount:项目流水线传递的最大项目数

用户代理

通过设置用户代理,你可以模仿真实的浏览器来提高搜索结果。网站对刮擦者并不满意,会试图阻止任何看起来不真实的用户代理。你可以使用这样的工具来获取你的浏览器用户代理。

WebScrapingAPI会在每次请求时轮换用户代理和 IP 地址,并实施无数的规避措施来防止此类情况的发生。您的请求不会被阻止,而重试机制的实施会给您带来亚马逊式的结果。

管道

管道是自上而下处理的命令,可以对处理过的项目进行操作。我们使用以下管道:

  • 验证字段(标题、价格、url):检查项目是否设置了刮擦字段
  • 重复过滤器:按标题检查重复项目
  • JSON 编码器:将结构编码为 JSON 对象
  • 写入文件:将项目写入 ./temp 文件夹

创建蜘蛛

网络爬虫(或称蜘蛛)是一种机器人,它通过 CSS 选择器,使用用户定义的字段浏览网站并提取数据。爬虫可以提取页面上的所有链接,并使用特定链接(如分页链接)抓取更多数据。 

现在是设置爬虫基础的时候了:在 lib/elixir_spider 文件夹中创建 ebay_scraper.ex 文件,并粘贴以下代码:

# lib/elixir_spider/ebay.ex
defmodule EbayScraper do
use Crawly.Spider

@impl Crawly.Spider
def base_url(), do:""

@impl Crawly.Spider
def init() do

end

@impl Crawly.Spider
def parse_item(response) do

end
end

这只是文件的骨架,不会运行或返回任何结果。让我们先谈谈每个函数,然后再逐一填写。

base_url()函数只调用一次,它会返回爬虫将抓取的目标网站的基本 URL;它还用于过滤外部链接,防止爬虫跟踪这些链接。我们并不想抓取整个互联网,因此,我们需要一个 "base_url "函数。

@impl Crawly.Spider
def base_url(), do:"https://www.ebay.com/"

init()函数会被调用一次,用于初始化爬虫的默认状态;在这种情况下,该函数会返回开始抓取的 start_url。

用这个功能替换您的空白功能:

@impl Crawly.Spider
def init() do
[start_urls:["https://www.ebay.com/sch/i.html?_nkw=ps5"]]
end

所有神奇的数据提取都发生在parse_item()函数中。我们会为每个获取的 URL 调用该函数。在这个函数中,我们使用 Floki HTML 解析器来提取我们需要的字段:标题、URL 和价格。

函数将如下所示:

@impl Crawly.Spider
def parse_item(response) do
# Parse response body to document
{:ok, document} = Floki.parse_document(response.body)

# Create item (for pages where items exists)
items =
document
|> Floki.find(".srp-results .s-item")
|> Enum.map(fn x ->
%{
title: Floki.find(x, ".s-item__title span") |> Floki.text(),
price: Floki.find(x, ".s-item__price") |> Floki.text(),
url: Floki.find(x, ".s-item__link") |> Floki.attribute("href") |> Floki.text(),
}
end)

%{items: items}
end

您可能已经注意到,我们正在使用 "入门--检查目标 "部分中的类,从 DOM 元素中提取我们需要的数据。

运行蜘蛛

现在是测试代码并确保其正常运行的时候了。在项目根目录下运行以下命令:

iex -S mix run -e "Crawly.Engine.start_spider(EbayScraper)"

如果使用 PowerShell,请确保将 iex 替换为 iex.bat,否则会因 -S 参数不存在而出错。在 PowerShell 中使用此命令:

iex.bat -S mix run -e "Crawly.Engine.start_spider(EbayScraper)"

检查结果

打开 ./temp 文件夹,检查 .jl 文件。你会看到一个文本文件,其中包含一个 JSON 对象列表,每行一个。每个对象都包含我们需要的 eBay 产品列表信息:标题、价格和 URL。

下面是产品对象的外观:

{"url":"https://www.ebay.com/itm/204096893295?epid=19040936896&hash=item2f851f716f:g:3G8AAOSwNslhoSZW&amdata=enc%3AAQAHAAAA0Nq2ODU0vEdnTBtnKgiVKIcOMvqJDPem%2BrNHrG4nsY9c3Ny1bzsybI0zClPHX1w4URLWSfXWX%2FeKXpdgpOe%2BF8IO%2FCh77%2FycTnMxDQNr5JfvTQZTF4%2Fu450uJ3RC7c%2B9ze0JHQ%2BWrbWP4yvDJnsTTWmjSONi2Cw71QMP6BnpfHBkn2mNzJ7j3Y1%2FSTIqcZ%2F8akkVNhUT0SQN7%2FBD38ue9kiUNDw9YDTUI1PhY14VbXB6ZMWZkN4hCt6gCDCl5mM7ZRpfYiDaVjaWVCbxUIm3rIg%3D%7Ctkp%3ABFBMwpvFwvRg","title":"PS5 Sony PlayStation 5 Console Disc Version!  US VERSION!","price":"$669.99"}

改进蜘蛛

我们从第一个产品列表页面提取了所有产品,但这还不够。现在应该实施分页,让爬虫提取所有可用的产品。

让我们更改parse_item()函数,并添加一个新代码块,创建一个包含下一个分页链接的请求结构。将此代码添加到 items 代码之后:

# 提取下一页链接并将其转换为请求
requests =
document
|> Floki.find(".s-pagination a.pagination__next")
|> Floki.attribute("href")
|> Crawly.Utils.build_absolute_urls(response.request_url)
|> Crawly.Utils.requests_from_urls()

更新parse_item()函数的返回语句,使其也包含下一个请求。结构将如下所示

%{
:requests => requests,
:items => items
}

再次运行爬虫,但这次要准备一杯咖啡。搜索 PS5 列表的所有页面需要几分钟时间。

爬虫完成任务后,检查 ./temp 文件夹中的搜索结果。您已成功在 eBay 上搜索到 PS5 游戏机,并获得了一份包含其价格的清单。您可以扩展此爬虫,搜索其他产品。

结论

在这篇文章中,你将了解到什么是网络爬虫、这些爬虫有哪些用例、如何使用已有库在几分钟内使用 Elixir 设置一个爬虫,以及如何运行和提取实际数据。

如果你觉得工作量很大,我想告诉你一个不太好的消息:我们只是做了表面文章。长时间运行这个刮板,会引发你想不到的问题。

eBay 会检测到您的活动并将其标记为可疑活动;爬虫会开始获取验证码补丁;您必须扩展爬虫功能以解决验证码问题

eBay 的检测系统可能会标记你的 IP 地址并阻止你访问网站;你必须使用代理池并在每次请求时轮换 IP 地址。 

是不是已经头晕目眩了?让我们再讨论一个问题:用户代理。你需要建立一个包含用户代理的大型数据库,并在每次请求时轮换该值。检测系统会根据 IP 地址和用户代理拦截搜索器。

如果你想把更多精力放在业务方面,把时间投入到数据提取而不是解决检测问题上,那么使用刮板作为服务是更好的选择。像WebScrapingAPI这样的解决方案可以解决上述所有问题,还能解决更多问题。 

新闻和更新

订阅我们的时事通讯,了解最新的网络搜索指南和新闻。

We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

相关文章

缩图
网络抓取科学Scrapy 与 Selenium:选择最佳网络抓取工具综合指南

探索 Scrapy 和 Selenium 在网络刮擦方面的深入比较。从大规模数据采集到处理动态内容,了解两者的优缺点和独特功能。了解如何根据项目需求和规模选择最佳框架。

WebscrapingAPI
作者头像
WebscrapingAPI
14 分钟阅读
缩图
指南Scrapy Splash 教程:掌握使用 Scrapy 和 Splash 抓取 JavaScript 渲染的网站的艺术

学习如何使用 Scrapy 和 Splash 抓取 JavaScript 渲染的动态网站。从安装到编写 spider、处理分页和管理 Splash 响应,本综合指南为初学者和专家提供了循序渐进的指导。

Ștefan Răcila
作者头像
Ștefan Răcila
6 分钟阅读
缩图
指南在线职位搜索终极指南,它的利与弊

在线职位搜索的定义和用途。职位搜索的优缺点、策略和潜在风险。

Suciu Dan
作者头像
Suciu Dan
8 分钟阅读