在 Go 中,使用 net/http 包可以轻松实现一个简单的爬虫。基本的爬虫通常需要以下几个步骤:

  1. 向目标网站发送 HTTP 请求。
  2. 获取并解析响应(如 HTML)。
  3. 提取并处理其中的链接或其他数据。
  4. 遇到新的链接时,递归地爬取。

下面是一个简单的示例,展示了如何使用 Go 的 net/http/x/net/html 包来抓取网页并解析其中的链接。

示例代码:简单的 HTTP 爬虫

package main

import (
	"fmt"
	"/x/net/html"
	"net/http"
	"os"
	"log"
	"strings"
)

func main() {
	url := "https://example.com" // 你想爬取的目标URL
	// 调用爬取函数
	links, err := getLinks(url)
	if err != nil {
		log.Fatal(err)
	}

	// 打印所有爬到的链接
	for _, link := range links {
		fmt.Println(link)
	}
}

// getLinks 请求页面并解析其中的所有链接
func getLinks(url string) ([]string, error) {
	// 发起 HTTP 请求
	resp, err := http.Get(url)
	if err != nil {
		return nil, fmt.Errorf("请求失败: %v", err)
	}
	defer resp.Body.Close()

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("响应错误: %v", resp.StatusCode)
	}

	// 解析 HTML
	doc, err := html.Parse(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("HTML解析失败: %v", err)
	}

	// 提取页面中的链接
	var links []string
	var f func(*html.Node)
	f = func(n *html.Node) {
		if n.Type == html.ElementNode && n.Data == "a" {
			// 提取 <a> 标签的 href 属性
			for _, attr := range n.Attributes {
				if attr.Key == "href" {
					link := attr.Val
					// 过滤掉空链接和不以 http 或 https 开头的链接
					if link != "" && (strings.HasPrefix(link, "http") || strings.HasPrefix(link, "https")) {
						links = append(links, link)
					}
					break
				}
			}
		}
	}
	// 遍历 HTML 文档
	_ = traverseHTML(doc, f)

	return links, nil
}

// traverseHTML 遍历 HTML 文档的节点
func traverseHTML(n *html.Node, f func(*html.Node)) {
	if n == nil {
		return
	}
	f(n)
	for c := n.FirstChild; c != nil; c = c.NextSibling {
		traverseHTML(c, f)
	}
}

代码说明:

  1. HTTP 请求:使用 http.Get(url) 发起 HTTP 请求获取页面内容。
  2. HTML 解析:使用 /x/net/html 包解析 HTML 文档。html.Parse 将返回一个 HTML 树的根节点。
  3. 提取链接:通过递归遍历 HTML 节点,找到 <a> 标签并提取其 href 属性,得到页面上的链接。
  4. 过滤链接:为了避免抓取到不相关的链接(如空链接、相对路径链接等),我们只提取以 httphttps 开头的链接。

如何运行:

  1. 安装依赖:运行爬虫前,需要安装 /x/net/html 包:
go get /x/net/html
  1. 运行代码:直接运行 go run main.go,如果目标 URL 存在,程序会爬取并打印出页面中的所有链接。

示例输出:

假设爬取的页面包含以下链接:

https://example.com/about
https://example.com/contact
https://example.com/privacy

爬虫将输出:

https://example.com/about
https://example.com/contact
https://example.com/privacy

注意事项:

  • 爬取频率:在实际爬虫中,频繁请求服务器可能会导致服务器负担过重或触发反爬虫机制。可以考虑加入延时、限制请求频率等。
  • 爬虫礼仪:请遵守目标网站的 robots.txt 文件规则,避免爬取不允许的页面。
  • 递归爬取:如果想要递归地爬取其他链接,可以在提取到链接后再次调用 getLinks 对这些链接进行爬取。要注意设置深度限制和防止爬虫陷入死循环。

进一步优化:

  • 你可以增加并发请求来提高爬取速度,使用 Go 的 goroutine 和 channel 来并发地抓取多个页面。
  • 使用 Go 的 time.Sleep 来控制爬取间隔,避免过于频繁的请求导致被封禁。