如何使用 Go 开始网络抓取的终极指南
索林-加布里埃尔-马里卡(Sorin-Gabriel Marica),2022 年 10 月 14 日
使用 Go 进行网络刮擦是创建快速而强大的刮擦工具的好方法。这是因为 GoLang 是并发性最好的编程语言之一。不过,在开始使用之前,我必须先向你详细介绍一下什么是网络搜刮,以及它能如何帮助你。
网络抓取是从网站中提取数据的过程。这个过程可以手动完成,但在处理大量数据时不建议使用这种方法。在本文中,我们将探讨如何使用 Go 从零开始构建自己的自动网络搜索器。
如果你是新手,你可能会想知道网络抓取有哪些用例。下面列出了一些最常见的情况:
- 价格比较工具 - 您可以使用网络搜刮工具创建许多工具。其中最常见、最有用的就是价格比较工具。这种工具会从多个来源搜索产品价格,并尽可能显示最优惠的价格。
- 机器学习 - 如果您想使用机器学习建立一个模型,您需要一个训练数据集。虽然有时您可能会找到可以使用的现有数据集,但很多时候您需要做一些额外的工作,自己获取所需的数据。
- 市场调研 - 第三种使用情况是从互联网上获取信息,了解竞争对手是谁以及他们在做什么。这样,您就可以跟上或领先于竞争对手,了解他们可能添加的任何新功能。
使用 go 搜刮数据需要什么?
在开始之前,您需要在机器上运行 GoLang 代码。为此,您只需安装 Go(如果尚未安装)。有关如何安装 Go 以及如何检查是否已安装的详细信息,请点击此处。
您还需要一个集成开发环境或文本编辑器,我们将在其中编写代码。我更喜欢使用 Visual Studio Code,但也可以使用任何你认为合适的工具。
就是这样。很简单,不是吗?现在,让我们进入本文的主题--使用 go 进行网络搜索。
使用 Go 构建网络搜索器
要构建我们的 scraper,我们首先需要一个目的,一组我们想从特定来源收集的数据。因此,我选择了从 npmjs.com 每周下载第一批使用关键字 "framework "的软件包,作为我们刮擦工具的主题。您可以在此页面找到它们:https://www.npmjs.com/search?q=keywords:framework&page=0&ranking=optimal)
检查要搜索的页面内容
要正确地进行刮擦,在开始实际提取数据之前,您需要了解数据的位置。我的意思是说,你需要根据页面的 HTML 结构,建立 HTML 选择器来查询数据。
要查看页面的 HTML 结构,可以使用大多数现代浏览器提供的开发工具。在 Chrome 浏览器中,您可以在页面上右键单击要提取的元素,然后单击 "检查页面"。完成后,您将看到如下内容:

根据右侧(检查窗口)显示的 HTML,我们现在可以创建要使用的选择器。在这个页面中,我们只需要每个软件包的 URL。
By looking over the HTML, we can see that the css classes used by the website are code generated. This makes them not reliable for scraping so we will use the html tags instead. On the page we can see that the packages are in <section> tags and that the link to the package is in the first div from the first div of the section.
Knowing this we can build the following selector to extract the links of all the packages: section > div:first-child > div:first-child a. Before trying it in code, we can test the selector from the developer tools of the browser. To do this go to the console tab and run document.querySelectorAll("{{ SELECTOR }}"):

将鼠标悬停在返回的每个节点列表元素上,我们可以看到它们正是我们要找的元素,因此我们可以使用这个选择器。
使用 Go 浏览页面
我们终于要开始构建刮板了!首先要创建一个文件夹,将所有代码放在其中。接下来,你需要从集成开发环境或操作系统中打开一个终端窗口,进入我们的文件夹。
要在文件夹中打开终端,可以使用 Visual Studio Code 点击终端 -> 新建终端(从顶部栏)。

现在我们已经打开了终端,是时候初始化项目了。运行以下命令即可:
go mod init webscrapingapi.com/my-go-scraper
这将在您的文件夹中创建一个名为 go.mod 的文件,内容如下:
module webscrapingapi.com/my-go-scraper
go 1.19
为了向页面发出请求并从 HTML 中提取选择器,我们将使用 GoLang 软件包 Colly(更多信息请查看 Colly 文档)。要安装该软件包,必须运行
go get github.com/gocolly/colly
现在一切准备就绪,我们需要做的就是创建main.go 文件并编写一些代码。从 npmjs 框架首页提取所有链接的代码如下:
package main
import (
"fmt"
"github.com/gocolly/colly"
)
func scrape() {
c := colly.NewCollector()
// Find and print all links
c.OnHTML("section > div:first-child > div:first-child a", func(e *colly.HTMLElement) {
fmt.Println(e.Attr("href"))
})
c.Visit("https://www.npmjs.com/search?q=keywords:framework&page=0&ranking=optimal")
}
func main() {
scrape()
}
如果一开始觉得难以理解,别担心,我们将在下面的段落中进行分解和解释。
每个 golang 文件都应该以软件包名称和 Go 将要使用的导入开始。在本例中,我们使用的两个包是 "fmt "和 "Colly"(分别用于打印搜索到的链接和实际的搜索)。
在下一部分中,我们创建了函数scrape(),它负责抓取我们需要的链接。为此,函数会访问第一页,等待找到我们决定的选择器。当该选择器中的元素出现时,它会继续打印该元素的 href 属性。
最后一部分是 main 函数,也就是每次运行 golang 脚本时都会调用的函数。要执行前面的代码,请在终端运行main.go,应该会得到以下输出:

正如你所看到的,href 属性包含链接的相对路径,因此我们需要在它的前缀加上 npmjs 网址。
利用 GoLang 的并发性提高效率
GoLang 最酷的功能之一是 GoRoutines。GoRoutines 是由 Go 运行时管理的简单轻量级线程。最棒的是,Go 可以帮助我们以迅雷不及掩耳之势同时搜索多个 url。
之前,我们提取了 npmjs.com 上关键字 "framework "下前 20 个软件包的链接。现在,我们将尝试同时抓取所有这些链接,并提取每个链接的每周下载量。为此,我们将使用 GoRoutines 和 WaitGroups。
以下是使用 goroutines 提取每周下载量的最终代码:
package main
import (
"fmt"
"github.com/gocolly/colly"
"sync"
)
func scrapeWeeklyDownloads(url string, wg *sync.WaitGroup) {
defer wg.Done()
c := colly.NewCollector()
// Find and print the weekly downloads value
c.OnHTML("main > div > div:last-child > div:not([class]) p", func(e *colly.HTMLElement) {
fmt.Println(fmt.Sprintf("%s - %s", url, e.Text))
})
c.Visit(url)
}
func scrape() {
c := colly.NewCollector()
var wg sync.WaitGroup
// Find and print all links
c.OnHTML("section > div:first-child > div:first-child a", func(e *colly.HTMLElement) {
wg.Add(1)
go scrapeWeeklyDownloads(fmt.Sprintf("%s%s", "https://www.npmjs.com", e.Attr("href")), &wg)
})
c.Visit("https://www.npmjs.com/search?q=keywords:framework&page=0&ranking=optimal")
wg.Wait()
}
func main() {
scrape()
}
现在,让我们来讨论一下在之前的代码中添加了哪些内容。首先,你会发现我们导入了一个名为 "sync "的新软件包。这将帮助我们使用 golang 例程,并在停止执行程序之前等待线程结束。
接下来要添加的是名为 "srapeWeeklyDownloads "的新函数。该函数接受两个参数:我们要搜刮的链接的 url 和 WaitGroup 指针。该函数的作用是访问给定的网址并提取每周的下载量(使用选择器main > div > div:last-child > div:not([class]) p)。
你将注意到的最后一个变化是在 scrape 函数中,我们使用var wg sync.WaitGroup 创建了一个 WaitGroup。在这里,对于软件包页面上的每个链接,我们都使用了wg.Add(1),然后创建了一个 GoRoutine 来调用 scrapeWeeklyDownloads 函数。在函数末尾,指令wg.Wait()使代码等待所有 GoRoutine 执行完毕。
有关 WaitGroups 的更多信息,请查看golang 提供的示例。
为什么选择 GoRoutines 和 WaitGroups?
通过在 golang 中使用 GoRoutines 和 WaitGroups 的并发功能,我们可以创建一个非常快速的搜刮器。运行前面的代码示例将返回每个软件包的页面和每周下载量。但是,由于我们使用的是多线程,这些信息的显示顺序还不得而知(因为线程的执行速度不同)
如果使用 linux 或 windows subsystem linux (wsl) 运行代码,可以使用time go run main.go查看整个脚本的执行时间。对我来说,执行时间大约为 5 到 6 秒。考虑到我们要扫描 21 个页面(首先是包含软件包的页面,然后是每个软件包的页面),这个速度已经非常快了。
其他障碍
大多数刮擦程序通常依靠向页面发出简单的 HTTP 请求来获取所需的内容。这种解决方案很好,但有时网站会通过 javascript 渲染来显示信息。这意味着网站首先只向你展示部分内容,其余部分则通过 javascript 动态加载。
要抓取此类页面,您需要使用 chromedriver 并控制一个真正的 Chrome 浏览器。虽然 Golang 中也有一些实现此功能的选项,但您需要对该主题进行一些额外的研究。
即使覆盖了 javascript 渲染功能,在搜索网站时仍会遇到一些额外的障碍。有些网站可能会使用反机器人检测、IP 屏蔽或验证码来防止机器人搜刮其内容。要想继续搜刮这些网站,你可以尝试使用一些网络搜刮的技巧和窍门,比如让你的搜刮器速度更慢,表现得更像人类。
但是,如果你想保持刮擦速度并以简单的方式解决这些障碍,你可以使用WebScrapingAPI。WebScrapingAPI 是一个 API,旨在通过旋转 IP 和避免反机器人检测来帮助您进行搜刮。这样,您就可以继续使用 GoLang 提供的闪电般的速度,并立即刮擦您的数据。
关于使用 Go 进行网络抓取的结论
网络抓取是从互联网上提取数据的一种快速有效的方法,可用于多种不同的用例。您可以选择为机器学习模型提取数据,也可以使用抓取的数据从头开始构建应用程序。
在并发性方面,GoLang 是最好的解决方案之一。使用 GoLang 和 Colly,您可以构建一个快速的搜刮器,它能在短时间内为您带来数据。一旦你习惯了 Go 的语法,使用 Go 进行网络搜刮就会变得非常简单高效。
新闻和更新
订阅我们的时事通讯,了解最新的网络搜索指南和新闻。
We care about the protection of your data. Read our <l>Privacy Policy</l>.Privacy Policy.

相关文章



学习如何使用 Golang 搜刮 HTML 表格以进行强大的数据提取。探索 HTML 表格的结构,并使用 Golang 的简洁性、并发性和强大的标准库构建网络刮擦工具。


了解如何将代理与流行的 JavaScript HTTP 客户端 node-fetch 结合使用,以构建网络搜刮程序。了解代理在网络搜刮中的工作原理,将代理与 node-fetch 集成,并构建一个支持代理的网络搜刮程序。
