golang网站食谱数据抓取与解析插件库go-recipe的使用
golang网站食谱数据抓取与解析插件库go-recipe的使用
go-recipe 是一个用于从网站抓取食谱数据的 Go 库。
安装
$ go get github.com/kkyr/go-recipe@latest
使用示例
下面是一个完整的示例代码,展示如何使用 go-recipe 抓取和解析食谱数据:
package main
import (
"fmt"
"github.com/kkyr/go-recipe/pkg/recipe"
)
func main() {
// 指定要抓取的食谱URL
url := "https://minimalistbaker.com/quick-pickled-jalapenos/"
// 使用ScrapeURL函数抓取食谱数据
recipe, err := recipe.ScrapeURL(url)
if err != nil {
fmt.Printf("抓取食谱失败: %v\n", err)
return
}
// 获取食谱名称
if name, ok := recipe.Name(); ok {
fmt.Printf("食谱名称: %s\n", name)
}
// 获取食材列表
if ingredients, ok := recipe.Ingredients(); ok {
fmt.Println("\n食材:")
for _, ing := range ingredients {
fmt.Printf("- %s\n", ing)
}
}
// 获取制作步骤
if instructions, ok := recipe.Instructions(); ok {
fmt.Println("\n制作步骤:")
for i, step := range instructions {
fmt.Printf("%d. %s\n", i+1, step)
}
}
// 获取烹饪时间
if cookTime, ok := recipe.CookTime(); ok {
fmt.Printf("\n烹饪时间: %s\n", cookTime)
}
// 获取准备时间
if prepTime, ok := recipe.PrepTime(); ok {
fmt.Printf("准备时间: %s\n", prepTime)
}
// 获取总时间
if totalTime, ok := recipe.TotalTime(); ok {
fmt.Printf("总时间: %s\n", totalTime)
}
// 获取份量
if yield, ok := recipe.Yield(); ok {
fmt.Printf("份量: %s\n", yield)
}
}
工作原理
go-recipe 的默认抓取器会查找目标网站上的 ld+json
编码的 Schema Recipe 数据,并能够检索模式中定义的大多数字段。然而,有些网站的 Schema 数据不完整,或者根本没有以这种格式编码食谱。
因此,go-recipe 提供了针对特定网站的自定义抓取器。这些抓取器可以利用默认抓取器,仅对默认抓取器无法找到数据的字段定义自定义抓取逻辑。
贡献
欢迎贡献!您可以通过以下几种方式做出贡献:
- 添加自定义抓取器
- 修复bug
- 基于路线图实现功能
- 添加您希望看到的其他功能
创建自定义抓取器
使用 go-recipe 包含的代码生成器可以轻松创建自定义抓取器。生成器需要两个参数:食谱网站的链接和托管食谱的网站域名。
运行以下命令(在 go-recipe 包目录中):
$ go run cmd/scrapergen/*.go \
-d CopyKat \
-u https://copykat.com/dunkin-donuts-caramel-iced-coffee
(将域名和链接替换为您自己的)
重要提示:域名应以 PascalCase 形式提供,以便生成的结构体大小写正确。否则,您的 PR 将不会被批准。
上面的示例命令将生成以下文件:
go-recipe/internal/html/scrape/custom/copykat.go
go-recipe/internal/html/scrape/custom/copykat_test.go
go-recipe/internal/html/scrape/custom/testdata/copykat.com.html
生成器还不能完成所有工作,因此您还需要进行一些最后的调整:
- 在
pkg/recipe/scrapers.go
中的hostToScraper
映射中注册您的自定义抓取器 - (可选)修改自定义抓取器以添加您自己的抓取逻辑
- 验证生成的测试是否正确
- 验证
make lint
和make test
是否通过
路线图
- [ ] 重构
scrapergen
并添加单元测试 - [ ] 修改
scrapergen
使其也将新抓取器添加到hostToScraper
映射中 - [ ] 添加选项让用户指定 HTTP 客户端超时
- [ ] 添加选项让用户指定"严格"模式:在此模式下仅使用自定义抓取器(如果已定义),否则失败
- [ ] 添加更多 Schema Recipe 字段
- [ ] 添加 CLI 包装器,以 JSON 格式提供输出
致谢
go-recipe 深受 recipe-scrapers 的启发。
更多关于golang网站食谱数据抓取与解析插件库go-recipe的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
更多关于golang网站食谱数据抓取与解析插件库go-recipe的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
使用go-recipe进行食谱数据抓取与解析
go-recipe是一个用于抓取和解析网站食谱数据的Golang库,它能够从各种食谱网站提取结构化数据,如食材、步骤、营养信息等。下面我将介绍如何使用这个库。
安装
go get github.com/kkyr/go-recipe
基本用法
1. 从URL抓取食谱
package main
import (
"fmt"
"log"
"github.com/kkyr/go-recipe/pkg/recipe"
)
func main() {
// 示例食谱URL
url := "https://www.allrecipes.com/recipe/158968/spinach-and-feta-turkey-burgers/"
// 创建抓取器
scraper, err := recipe.NewScraper(url)
if err != nil {
log.Fatalf("创建抓取器失败: %v", err)
}
// 抓取食谱数据
recipe, err := scraper.Scrape()
if err != nil {
log.Fatalf("抓取失败: %v", err)
}
// 打印食谱信息
fmt.Printf("食谱标题: %s\n", recipe.Name)
fmt.Printf("作者: %s\n", recipe.Author)
fmt.Printf("准备时间: %s\n", recipe.PrepTime)
fmt.Printf("烹饪时间: %s\n", recipe.CookTime)
fmt.Printf("总时间: %s\n", recipe.TotalTime)
fmt.Printf("份量: %s\n", recipe.Yield)
fmt.Printf("评分: %.1f/5 (%d票)\n", recipe.Rating.Value, recipe.Rating.Count)
fmt.Println("\n食材:")
for _, ingredient := range recipe.Ingredients {
fmt.Printf("- %s\n", ingredient)
}
fmt.Println("\n步骤:")
for i, instruction := range recipe.Instructions {
fmt.Printf("%d. %s\n", i+1, instruction)
}
fmt.Println("\n营养信息:")
for k, v := range recipe.Nutrition {
fmt.Printf("%s: %s\n", k, v)
}
}
2. 支持的网站
go-recipe支持许多流行的食谱网站,包括:
- AllRecipes
- BBC Good Food
- Bon Appétit
- Epicurious
- Food Network
- 以及更多…
你可以通过recipe.SupportedDomains()
查看完整列表:
func main() {
domains := recipe.SupportedDomains()
fmt.Println("支持的网站:")
for _, domain := range domains {
fmt.Println("-", domain)
}
}
高级功能
1. 自定义HTTP客户端
func main() {
client := &http.Client{
Timeout: 30 * time.Second,
}
scraper, err := recipe.NewScraper(
"https://www.example.com/recipe",
recipe.WithHTTPClient(client),
)
// ...
}
2. 处理图片
func main() {
scraper, err := recipe.NewScraper(url)
// ...
recipe, err := scraper.Scrape()
// ...
// 获取食谱图片URL
if recipe.Image != nil {
fmt.Printf("图片URL: %s\n", recipe.Image.URL)
fmt.Printf("图片宽度: %d\n", recipe.Image.Width)
fmt.Printf("图片高度: %d\n", recipe.Image.Height)
}
}
3. 处理分类和标签
func main() {
scraper, err := recipe.NewScraper(url)
// ...
recipe, err := scraper.Scrape()
// ...
fmt.Println("分类:")
for _, category := range recipe.Categories {
fmt.Println("-", category)
}
fmt.Println("标签:")
for _, keyword := range recipe.Keywords {
fmt.Println("-", keyword)
}
}
注意事项
- 在使用前请检查目标网站的robots.txt文件,确保允许爬取
- 合理设置请求间隔,避免对网站造成过大负担
- 网站结构可能变化,需要定期更新解析逻辑
- 考虑使用缓存机制避免重复抓取
错误处理
func main() {
scraper, err := recipe.NewScraper(url)
if err != nil {
switch {
case errors.Is(err, recipe.ErrDomainNotSupported):
fmt.Println("不支持的网站域名")
case errors.Is(err, recipe.ErrInvalidURL):
fmt.Println("无效的URL")
default:
fmt.Printf("未知错误: %v\n", err)
}
return
}
recipe, err := scraper.Scrape()
if err != nil {
fmt.Printf("抓取失败: %v\n", err)
return
}
// ...
}
go-recipe是一个强大的工具,可以大大简化从各种食谱网站提取结构化数据的过程。通过合理使用,你可以构建自己的食谱数据库、分析工具或个性化推荐系统。