返回博客
指南
安德烈·奥吉奥兰2023年4月24日阅读时间:9分钟

了解如何使用 Golang 抓取 HTML 表格

了解如何使用 Golang 抓取 HTML 表格

导言

网络爬虫是一种从网站中提取数据的技术,也是从互联网收集信息的有力工具。本文将探讨如何使用Go语言(一种以简单易用、支持并发以及功能强大的标准库而闻名的流行编程语言)来爬取HTML表格。

什么是 HTML 表格?

HTML tables are a type of element in HTML (Hypertext Markup Language) that is used to represent tabular data on a web page. An HTML table consists of rows and columns of cells containing text, images, or other HTML elements. HTML tables are created using the table element, and are structured using the ‘<tr>’ (table row),‘<td>’ (table cell), ‘<th>’ (table header), ‘<caption>’, ‘<col>’, ‘<colgroup>’, ‘<tbody>’ (table body), ‘<thead>’ (table head) and ‘<tfoot>’ (table foot) elements. Now let’s go through each one and get into more detail:

  • table 元素:定义 HTML 表格的起始和结束。
  • tr(表格行)元素:定义HTML表格中的一行。
  • td(表格单元格)元素:定义HTML表格中的一个单元格。
  • th(表格标题)元素:用于定义HTML表格中的标题单元格。标题单元格默认以粗体居中显示,用于标注表格的行或列。
  • caption 元素:用于为 HTML 表格定义标题。该标题通常显示在表格上方或下方。
  • col 和 colgroup 元素:用于定义 HTML 表格中各列的属性,例如宽度或对齐方式。
  • tbody、thead 和 tfoot 元素:分别定义 HTML 表格的主体、表头和表尾部分。这些元素可用于将行分组,并为表格的特定部分应用样式或属性。

为了更好地理解这个概念,让我们来看看 HTML 表格是什么样子的:

Playwright、Puppeteer 和 Selenium 在速度、文档和浏览器支持方面的对比表

乍一看,这似乎是一个普通的表格,我们无法看到包含上述元素的结构。这并不意味着这些元素不存在,而是说明浏览器已经为我们解析了这些内容。为了查看 HTML 结构,你需要深入一步,使用开发者工具。 具体操作方法是:右键点击页面,选择“检查”,点击“选择元素”工具,然后点击你想查看其HTML结构的元素(本例中为 table)。完成这些步骤后,你应该会看到类似以下的内容:

包含示例表格的 HTML 表格教程页面,并配有浏览器开发者工具对表格标记的突出显示

HTML 表格通常用于以结构化的表格形式呈现数据,例如整理结果或显示数据库内容。它们广泛存在于各类网站中,也是从网络上抓取数据时需要重点考虑的重要元素。

设置

在开始数据抓取之前,我们需要配置 Go 开发环境并安装必要的依赖项。请确保您的系统已安装并配置好 Go 语言,然后创建一个新的项目目录并初始化 `go.mod` 文件:

$ mkdir scraping-project

$ cd scraping-project

$ go mod init <NAME-OF-YOUR-PROJECT>

$ touch main.go

接下来,我们需要安装一个用于发送 HTTP 请求和解析 HTML 的库。虽然有多种选择,但本文将使用标准库中的 `net/http` 包以及用于解析 HTML 的golang.org/x/net/html包。可以通过运行以下命令安装这些包:

$ go get -u net/http golang.org/x/net/html

现在环境已经搭建完毕,我们可以开始使用 Golang 编写 HTML 表格抓取程序了。

让我们开始抓取数据吧

现在环境已经搭建完毕,我们可以开始编写一个爬虫程序,从 HTML 表格中提取数据。第一步是向包含目标 HTML 表格的网页发送一个 HTTP 请求。我们可以使用 `net/http` 包中的 `http.Get` 函数来发送 GET 请求并获取 HTML 内容:

package main

import (

	"fmt"

	"io/ioutil"

	"log"

	"net/http"

)

func main() {

	resp, err := http.Get("https://www.w3schools.com/html/html_tables.asp")

	if err != nil {

		log.Fatal(err)

	}

	defer resp.Body.Close()

	// Read the response body and convert it to a string

	body, err := ioutil.ReadAll(resp.Body)

	if err != nil {

		log.Fatal(err)

	}

	html := string(body)

	fmt.Println(html)

}

接下来,我们可以使用goquery包中的 `goquery.NewDocumentFromReader` 函数来解析 HTML 内容并提取所需数据。与其他 Go 语言包一样,您需要先按照以下方式安装它:

$ go get github.com/PuerkitoBio/goquery 

然后添加以下代码,用于解析页面的 HTML:

doc, err := goquery.NewDocumentFromReader(resp.Body)

if err != nil {

    log.Fatal(err)

}

既然我们已经有了用于解析 HTML 的解析器和元素提取器,就可以利用 Goquery 包中的 `doc.Find()` 功能来查找我们需要的特定元素,在本例中即为一个表格。具体使用方法如下:

doc.Find("table").Each(func(i int, sel * goquery.Selection) {

    // For sake of simplicity taking the first table of the page

    if i == 0 {

        // Looping through headers

        headers: = sel.Find("th").Each(func(_ int, sel * goquery.Selection) {

            if sel != nil {

                fmt.Print(sel.Text())

                fmt.Print(" ")

            }

        })

        fmt.Println()

        // Looping through cells

        sel.Find("td").Each(func(index int, sel * goquery.Selection) {

            if sel != nil {

                fmt.Print(sel.Text())

                fmt.Print(" ")

            }

            // Printing columns nicely

            if (index + 1) % headers.Size() == 0 {

                fmt.Println()

            }

        })

    }

})

就这样,现在你可以使用 Golang 抓取该表格了,屏幕上应该会显示如下内容:

终端输出显示了包含“公司”、“联系人”和“国家”列的刮取数据表行

您可能已经注意到,这种结构可能会让人感到困惑,且难以阅读。好消息是,您可以做得更好,将数据以表格形式美观地呈现出来,这样就易于阅读了。这正是tablewriter 包大显身手的好机会,您可以按以下方式安装该包:

$ go get github.com/olekukonko/tablewriter

现在,在将数据传递给表写入器之前,我们需要对代码进行一些调整,例如定义表头、结构体,并将它们存储到数组中。代码大致如下所示:

package main

import (

	"log"

	"net/http"

	"os"

	"github.com/PuerkitoBio/goquery"

	"github.com/olekukonko/tablewriter"

)

type Company struct {

	Company string

	Contact string

	Country string

}

func main() {

	resp, err := http.Get("https://www.w3schools.com/html/html_tables.asp")

	if err != nil {

		log.Fatal(err)

	}

	defer resp.Body.Close()

	// Read the response body and convert it to a string

	doc, err := goquery.NewDocumentFromReader(resp.Body)

	if err != nil {

		log.Fatal(err)

	}

	var companies []Company

	doc.Find("table").Each(func(i int, sel *goquery.Selection) {

		if i == 0 {

			e := Company{}

			sel.Find("td").Each(func(index int, sel *goquery.Selection) {

				if index%3 == 0 {

					e.Company = sel.Text()

				}

				if index%3 == 1 {

					e.Contact = sel.Text()

				}

				if index%3 == 2 {

					e.Country = sel.Text()

				}

                        // Add the element to our array

				if index != 0 && (index+1)%3 == 0 {

					companies = append(companies, e)

				}

			})

		}

	})

	table := tablewriter.NewWriter(os.Stdout)

	// Setting our headers

	table.SetHeader([]string{"Company", "Contact", "Country"})

	for _, Company := range companies {

		s := []string{

			Company.Company,

			Company.Contact,

			Company.Country,

		}

		table.Append(s)

	}

	table.Render()

}

现在,您应该能够看到以这种格式显示的数据:

终端输出显示了已抓取的公司、联系人及国家数据的ASCII表格

至此,你已经成功用 Go 语言编写了一个爬虫程序,能够抓取网页内容,并以美观的方式存储和展示数据。你还可以修改代码,从其他网站抓取表格数据。 请注意,并非所有网站都像这样容易抓取数据。许多网站都实施了高级防护措施来防止抓取,例如验证码(CAPTCHA)和IP地址封禁,但幸运的是,有WebScrapingAPI等第三方服务提供IP轮换和 验证码绕过功能,使你能够抓取这些目标网站。

深入探讨

虽然我们迄今为止介绍的技术对于简单的 HTML 表格来说已经足够,但仍有几种方法可以对其进行改进。

一个潜在的问题是,不同网页中的 HTML 表格结构可能不一致。例如,表格的列数可能不同,或者数据可能嵌套在不同的 HTML 元素中。为了处理这些情况,您可以使用更高级的技术(如 CSS 选择器或 XPath 表达式)来定位需要提取的数据。

另一个问题是,网页通常会使用 AJAX 或其他客户端技术,在页面加载到浏览器后继续加载额外数据。这意味着您正在抓取的 HTML 表格可能并不包含您所需的所有数据。 要抓取此类页面,您可能需要使用无头浏览器等工具,这类工具能够执行 JavaScript 并像普通网页浏览器一样渲染页面。另一个不错的替代方案是使用我们的抓取工具,它能在页面完成 JavaScript 渲染后返回数据。您可查阅我们的文档了解更多详情。

最后,必须考虑爬虫的性能和可扩展性。如果需要抓取大型表格或多页内容,您可能需要采用并发处理或速率限制等技术,以确保爬虫能够承受相应的负载。

摘要

希望这篇指南能成为您使用 Go 语言抓取 HTML 表格的良好起点。我们已经详细演示了如何使用 Go 编程语言从 HTML 表格中抓取数据。 我们探讨了如何获取网页的 HTML 内容,将其输出到屏幕上,并以表格形式呈现,以便人类阅读。此外,我们还讨论了在抓取 HTML 表格时可能遇到的一些挑战,包括表格结构不一致、客户端数据加载,以及性能和可扩展性问题。

虽然您可以利用本文所述的技术自行构建爬虫程序,但使用专业的数据抓取服务通常更为高效且可靠。这类服务具备完善的基础设施、专业技术以及安全措施,能够处理海量数据和复杂的抓取任务,并且通常能以CSV或JSON等结构化且便于使用的格式提供数据。

总而言之,抓取HTML表格是提取网络数据的一种有效方法,但必须仔细权衡自行开发抓取工具与使用专业服务之间的利弊。

关于作者
安德烈·奥吉奥兰,全栈开发工程师 @ WebScrapingAPI
安德烈-奥吉奥兰全栈开发工程师

安德烈·奥吉奥兰(Andrei Ogiolan)是 WebScrapingAPI 的全栈开发工程师,他在产品各领域均有贡献,并协助为该平台构建可靠的工具和功能。

开始构建

准备好扩展您的数据收集规模了吗?

加入2,000多家企业,使用WebScrapingAPI在无需任何基础设施开销的情况下,以企业级规模提取网页数据。