基于 Go1.19 的站点模板爬虫:构建与实战

引言

随着互联网的发展,网络爬虫已成为数据抓取和分析的重要工具。Go(Golang)语言凭借其高效、简洁的特性,成为构建爬虫的热门选择之一。本文将引导你使用 Go1.19 版本,构建一个基于站点模板的网页爬虫,以抓取指定网站的结构化数据。

环境准备

确保你的开发环境已安装 Go1.19 或更高版本。可以通过以下命令检查 Go 的版本:

Bash

深色版本

1go version

如果尚未安装 Go,可以从官方网站(https://golang.org/dl/)下载并按照指示进行安装。

工程结构

为了组织代码和资源,我们首先创建项目目录结构:

深色版本

1.
2├── cmd
3│   └── crawler.go
4├── internal
5│   ├── scraper
6│   │   └── scraper.go
7│   └── templates
8│       └── site.tmpl
9└── go.mod

cmd 目录下的 crawler.go 用于启动爬虫。internal/scraper 包含爬虫的核心逻辑,internal/templates 存放站点模板。

依赖管理

在项目根目录下创建或更新 go.mod 文件,添加所需的依赖包:

Go

深色版本

1module github.com/yourusername/gocrawler
2
3go 1.19
4
5require (
6    golang.org/x/net v0.0.0-20230511212614-fa735b7d40e0
7    gopkg.in/yaml.v3 v3.0.1
8)

然后运行以下命令以下载并安装依赖:

Bash

深色版本

1go mod download

爬虫核心逻辑

解析模板

internal/scraper/scraper.go 中,我们需要定义一个函数来解析站点模板,提取出需要爬取的数据点:

Go

深色版本

1package scraper
2
3import (
4	"fmt"
5	"html/template"
6	"io/ioutil"
7	"net/http"
8	"strings"
9
10	"gopkg.in/yaml.v3"
11)
12
13type SiteTemplate struct {
14	URL   string            `yaml:"url"`
15	Query map[string]string `yaml:"query"`
16}
17
18func LoadSiteTemplate(filename string) (*SiteTemplate, error) {
19	data, err := ioutil.ReadFile(filename)
20	if err != nil {
21		return nil, err
22	}
23
24	var templateConfig SiteTemplate
25	err = yaml.Unmarshal(data, &templateConfig)
26	if err != nil {
27		return nil, err
28	}
29
30	return &templateConfig, nil
31}
32
33func FetchAndParse(url string, query map[string]string) (string, error) {
34	client := &http.Client{}
35	req, err := http.NewRequest("GET", url, nil)
36	if err != nil {
37		return "", err
38	}
39
40	for k, v := range query {
41		req.URL.RawQuery = strings.Join([]string{req.URL.RawQuery, fmt.Sprintf("%s=%s", k, v)}, "&")
42	}
43
44	resp, err := client.Do(req)
45	if err != nil {
46		return "", err
47	}
48	defer resp.Body.Close()
49
50	bodyBytes, err := ioutil.ReadAll(resp.Body)
51	if err != nil {
52		return "", err
53	}
54
55	return string(bodyBytes), nil
56}
57
58func ParsePage(htmlContent string, template *template.Template) (map[string]interface{}, error) {
59	var data = make(map[string]interface{})
60	err := template.Execute(funcMap, htmlContent, &data)
61	if err != nil {
62		return nil, err
63	}
64
65	return data, nil
66}

爬虫启动器

cmd/crawler.go 中,我们将定义爬虫的入口函数:

Go

深色版本

1package main
2
3import (
4	"log"
5	"os"
6
7	"github.com/yourusername/gocrawler/internal/scraper"
8)
9
10func main() {
11	templatePath := "./internal/templates/site.tmpl"
12	siteTemplate, err := scraper.LoadSiteTemplate(templatePath)
13	if err != nil {
14		log.Fatalf("Error loading template: %v", err)
15	}
16
17	tmpl, err := template.ParseFiles(templatePath)
18	if err != nil {
19		log.Fatalf("Error parsing template: %v", err)
20	}
21
22	htmlContent, err := scraper.FetchAndParse(siteTemplate.URL, siteTemplate.Query)
23	if err != nil {
24		log.Fatalf("Error fetching page: %v", err)
25	}
26
27	parsedData, err := scraper.ParsePage(htmlContent, tmpl)
28	if err != nil {
29		log.Fatalf("Error parsing page: %v", err)
30	}
31
32	log.Printf("Parsed Data: %+v", parsedData)
33}

定义站点模板

internal/templates/site.tmpl 文件中,定义你的站点模板,使用 HTML 模板语法和 {{ . }} 占位符来提取数据:

Html

深色版本

1<!-- Example template -->
2<html>
3<head>
4<title>{{ .Title }}</title>
5</head>
6<body>
7<h1>Welcome to {{ .SiteName }}</h1>
8<ul>
9{{ range .Posts }}
10<li><a href="{{ .URL }}">{{ .Title }}</a></li>
11{{ end }}
12</ul>
13</body>
14</html>

运行爬虫

最后,从项目根目录运行爬虫:

Bash

深色版本

1go run ./cmd/crawler.go

结论

本文介绍了如何使用 Go1.19 构建一个基于站点模板的网页爬虫。通过定义模板和解析规则,我们可以灵活地抓取不同网站的数据。虽然示例中仅展示了基本的爬虫框架,但你可以在此基础上扩展更多功能,如错误处理、日志记录、并发控制等,以满足更复杂的需求。希望这篇文章能为你的爬虫开发之旅提供有益的启示!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/47664.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

npm安装依赖包的多种镜像及方法

一般安装依赖包&#xff0c;都是使用 npmjs 镜像安装&#xff0c;或者使用淘宝镜像安装。 比如&#xff1a; npm i react查看当前镜像&#xff1a; npm config get registry当面对 npmjs 镜像无法访问以及淘宝 npm 镜像&#xff08;cnpm&#xff09;SSL 证书过期的问题&…

PyTorch中的batch_size和num_workers

PyTorch中的batch_size和num_workers 什么是 batch_size&#xff1f;什么是 num_workers&#xff1f;综合考量 什么是 batch_size&#xff1f; batch_size 是指在每次迭代中送入模型进行训练的数据样本的数量。它对训练过程有着重要影响&#xff1a; 计算效率&#xff1a;较大…

数据仓库实践:使用 SQL 计算材料BOM成本单价

背景 在制造业财务数据分析建设过程中&#xff0c;有时需要通过BOM汇总计算材料的单价&#xff0c;一般会有采购核价&#xff0c;库存成本&#xff0c;还有下阶材料单价按用量汇总得到的单价参与。 这些单价来源一般会根据优先级获取并在计算后作为最终的BOM 单价结果。参与财…

GPT-5一年半后发布

GPT-5 一年半后发布&#xff1f;对此你有何期待&#xff1f; 一&#xff1a;GPT-5技术突破预测 GPT-5的推出预示着自然语言处理&#xff08;NLP&#xff09;领域将迎来前所未有的技术革新&#xff0c;这将从多个方面推动行业发展。首先&#xff0c;GPT-5在算法上的进步显著&…

防范UDP Flood攻击的策略与实践

UDP Flood攻击是一种常见的分布式拒绝服务&#xff08;DDoS&#xff09;攻击手段&#xff0c;通过向目标服务器发送大量无效的UDP数据包&#xff0c;消耗其网络带宽和处理资源&#xff0c;最终导致合法的网络服务无法正常运行。本文将深入探讨UDP Flood攻击的原理、常见的防御策…

iOS ------ 编译链接

编译流程分析 编译可以分为四步&#xff1a; 预处理&#xff08;Prepressing)编译&#xff08;Compilation&#xff09;汇编 &#xff08;Assembly)链接&#xff08;Linking&#xff09; 预编译&#xff08;Prepressing&#xff09; 过程是源文件main.c和相关头文件被&#…

SQL Server查询计划阅读及分析

​​​​​​6.4.5. 查询计划阅读及分析 SQL Server中,SQL语句的查询计划可能会包含多个节点,每个节点除了包含和对应一个操作符外,还包含节点及操作符相关的其他信息,其细节与具体的操作符相关。SQL Server查询计划与Oracle执行计划中,虽然每个节点所包含内容的具体称谓…

window11 部署llama.cpp并运行Qwen2-0.5B-Instruct-GGUF

吾名爱妃&#xff0c;性好静亦好动。好编程&#xff0c;常沉浸于代码之世界&#xff0c;思维纵横&#xff0c;力求逻辑之严密&#xff0c;算法之精妙。亦爱篮球&#xff0c;驰骋球场&#xff0c;尽享挥洒汗水之乐。且喜跑步&#xff0c;尤钟马拉松&#xff0c;长途奔袭&#xf…

FastAPI 学习之路(五十九)封装统一的json返回处理工具

在本篇文章之前的接口&#xff0c;我们每个接口异常返回的数据格式都不一样&#xff0c;处理起来也没有那么方便&#xff0c;因此我们可以封装一个统一的json。 from fastapi import status from fastapi.responses import JSONResponse, Response from typing import Unionde…

= null 和 is null;SQL中关于NULL处理的4个陷阱;三值逻辑

一、概述 1、NULL参与的所有的比较和算术运算符(>,,<,<>,<,>,,-,*,/) 结果为unknown&#xff1b; 2、unknown的逻辑运算(AND、OR、NOT&#xff09;遵循三值运算的真值表&#xff1b; 3、如果运算结果直接返回用户&#xff0c;使用NULL来标识unknown 4、如…

Go语言并发编程-Channel通信_2

Channel通信 Channel概述 不要通过共享内存的方式进行通信&#xff0c;而是应该通过通信的方式共享内存 这是Go语言最核心的设计模式之一。 在很多主流的编程语言中&#xff0c;多个线程传递数据的方式一般都是共享内存&#xff0c;而Go语言中多Goroutine通信的主要方案是Cha…

JavaEE:Lombok工具包的使用以及EditStarter插件的安装

Lombok是一个Java工具库&#xff0c;通过添加注解的方式&#xff0c;简化Java的开发。 目录 1、引入依赖 2、使用 3、原理解释 4、更多使用 5、更快捷的引入依赖 1、引入依赖 <dependency><groupId>org.projectlombok</groupId><artifactId>lomb…

pdf提取其中一页怎么操作?提取PDF其中一页的方法

pdf提取其中一页怎么操作&#xff1f;需要从一个PDF文件中提取特定页码的操作通常是在处理文档时常见的需求。这种操作允许用户选择性地获取所需的信息&#xff0c;而不必操作整个文档。通过选择性提取页面&#xff0c;你可以更高效地管理和利用PDF文件的内容&#xff0c;无论是…

结合Redis解决接口幂等性问题

结合Redis解决接口幂等性问题 引言正文收获 引言 该问题产生背景是根据需求描述&#xff0c;要求对已发布的课程能进行编辑修改&#xff0c;并且要求能进行回滚。 幂等性问题描述&#xff1a;对同一个接口并发请求产生的结果是不变的。 Get 请求以及 Delete 请求天然保证幂等…

Linux编辑器——vim的使用

目录 vim的基本概念 命令模式 底行模式 插入模式 注释和取消注释 普通用户进行sudo提权 vim配置问题 vim的基本概念 一般使用的vim有三种模式&#xff1a; 命令模式 底行模式和插入模式&#xff0c;可以进行转换&#xff1b; vim filename 打开vim&#xff0c;进入的…

【代码随想录|贪心算法 455. 分发饼干 376. 摆动序列 53. 最大子数组和】

代码随想录|贪心算法 455. 分发饼干 一、455. 分发饼干1.代码2.问题 二、376. 摆动序列1.代码 三、53. 最大子数组和1.代码 总结 python 一、455. 分发饼干 455. 分发饼干 1.代码 代码如下&#xff08;示例&#xff09;&#xff1a; class Solution:def findContentChildr…

ffmpeg ffplay.c 源码分析

1 ffplay.c的意义 ffplay.c是FFmpeg源码⾃带的播放器&#xff0c;调⽤FFmpeg和SDL API实现⼀个⾮常有⽤的播放器。 例如哔哩哔哩著名开源项⽬ijkplayer也是基于ffplay.c进⾏⼆次开发。 ffplay实现了播放器的主体功能&#xff0c;掌握其原理对于我们独⽴开发播放器⾮常有帮助…

junit mockito service

service类单元测试可以有两种方式 1、使用Autowired启用上下文的Bean走业务逻辑&#xff0c;适用于debug调试 2、使用InjectMocks不启用上下文依懒的Bean采用打桩的形式 打桩注意&#xff1a;service通常业务逻辑复杂&#xff0c;Bean的依懒层次可能很深&#xff0c;初用者常…

npm install时报错 reason: certificate has expired

在VS code中导入新项目&#xff0c;执行npm install时报错&#xff1a; npm warn old lockfile Could not fetch metadata for antv/g3.4.10 FetchError: request to https://registry.npm.taobao.org/antv%2fg failed, reason: certificate has expirednpm warn old lockfile …

[C/C++入门][for]25、药房管理(循环经典练习)

假设对于任意一种药品&#xff0c;每天开始工作时的库存总量已知&#xff0c;并且一天之内不会通过进货的方式增加。每天会有很多病人前来取药&#xff0c;每个病人希望取走不同数量的药品。如果病人需要的数量超过了当时的库存量&#xff0c;药房会拒绝该病人的请求。管理员希…