golang命令行网页爬虫与数据抓取插件库crawley的使用

Golang命令行网页爬虫与数据抓取插件库crawley的使用

特性

  • 快速HTML SAX解析器(基于x/net/html)
  • JavaScript/CSS词法解析器(基于tdewolff/parse) - 从JS代码和url()属性中提取API端点
  • 代码简洁(少于1500行),100%测试覆盖率
  • 抓取大多数有用的资源URL(图片、视频、音频、表单等)
  • 发现的URL会输出到stdout并保证唯一性(忽略片段)
  • 可配置扫描深度(默认0,限制在起始主机和路径)
  • 支持robots.txt规则和站点地图
  • brute模式 - 扫描HTML评论中的URL(可能导致虚假结果)
  • 支持HTTP_PROXY/HTTPS_PROXY环境变量和代理认证
  • 仅目录扫描模式(快速扫描)
  • 用户自定义cookie(支持curl格式)
  • 用户自定义headers(支持curl格式)
  • 标签过滤器 - 指定要抓取的标签
  • URL忽略 - 忽略包含特定子串的URL
  • 子域名支持

安装

  • 下载预编译二进制文件(适用于Linux、FreeBSD、macOS和Windows)
  • Archlinux用户可以使用AUR助手安装: paru -S crawley-bin

使用示例

# 打印第一页的所有链接:
crawley http://some-test.site

# 打印所有JS文件和API端点:
crawley -depth -1 -tag script -js http://some-test.site

# 打印JS中的所有端点:
crawley -js http://some-test.site/app.js

# 下载网站所有png图片:
crawley -depth -1 -tag img http://some-test.site | grep '\.png$' | wget -i -

# 快速目录遍历:
crawley -headless -delay 0 -depth -1 -dirs only http://some-test.site

完整命令行选项

crawley [flags] url

可用选项(默认值):

-all
    扫描所有已知来源(js/css/...)
-brute
    扫描HTML注释
-cookie value
    请求的额外cookie,可多次使用,支持'@'前缀文件
-css
    扫描CSS中的URL
-delay duration
    每个请求的延迟(0表示禁用)(默认150ms)
-depth int
    扫描深度(-1表示无限制)
-dirs string
    非资源URL的处理策略: show/hide/only(默认"show")
-header value
    请求的额外header,可多次使用,支持'@'前缀文件
-headless
    禁用预检HEAD请求
-ignore value
    爬取过程中要忽略的URL模式
-js
    扫描JS代码中的端点
-proxy-auth string
    代理认证信息: user:password
-robots string
    robots.txt处理策略: ignore/crawl/respect(默认"ignore")
-silent
    禁止在stderr输出信息和错误
-skip-ssl
    跳过SSL验证
-subdomains
    支持子域名(如找到www.domain.com也会爬取)
-tag value
    标签过滤器,单一或逗号分隔的标签名
-timeout duration
    请求超时(最小1秒,最大10分钟)(默认5s)
-user-agent string
    用户代理字符串
-version
    显示版本
-workers int
    工作线程数(默认CPU核心数)

自动补全

Crawley支持通过complete命令在bash和zsh中实现标志自动补全:

complete -C "/full-path-to/bin/crawley" crawley

许可证

MIT License

FOSSA Status


更多关于golang命令行网页爬虫与数据抓取插件库crawley的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html

1 回复

更多关于golang命令行网页爬虫与数据抓取插件库crawley的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html


使用Crawley构建Golang命令行网页爬虫

Crawley是一个强大的Go语言网页爬虫和数据抓取库,它提供了简洁的API和丰富的功能来帮助开发者快速构建爬虫应用。下面我将介绍如何使用Crawley构建一个命令行网页爬虫。

安装Crawley

首先,我们需要安装Crawley库:

go get github.com/slyrz/crawley

基本爬虫示例

下面是一个简单的Crawley爬虫示例,它可以抓取网页上的所有链接:

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/slyrz/crawley"
	"github.com/slyrz/crawley/filter"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run main.go <url>")
		return
	}

	url := os.Args[1]

	// 创建爬虫配置
	config := crawley.Config{
		MaxDepth:   2,               // 最大爬取深度
		MaxThreads: 5,               // 并发线程数
		UserAgent:  "MyCrawler/1.0", // 用户代理
	}

	// 创建爬虫实例
	crawler := crawley.NewCrawler(config)

	// 设置URL过滤器 - 只爬取同域名的链接
	domainFilter := filter.NewDomainFilter(url)
	crawler.AddFilter(domainFilter)

	// 设置响应处理器
	crawler.OnResponse(func(resp *crawley.Response) {
		fmt.Printf("Fetched: %s (Status: %d)\n", resp.URL, resp.StatusCode)
		
		// 提取页面中的所有链接
		links := resp.Links()
		for _, link := range links {
			fmt.Println("Found link:", link)
		}
	})

	// 设置错误处理器
	crawler.OnError(func(err error, url string) {
		log.Printf("Error fetching %s: %v\n", url, err)
	})

	// 开始爬取
	fmt.Printf("Starting crawl of %s...\n", url)
	crawler.Crawl(url)
	fmt.Println("Crawl completed!")
}

数据抓取功能

Crawley还提供了强大的数据抓取功能,可以使用CSS选择器或XPath来提取特定数据:

package main

import (
	"fmt"
	"log"
	"os"

	"github.com/slyrz/crawley"
	"github.com/slyrz/crawley/selector"
)

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run main.go <url>")
		return
	}

	url := os.Args[1]

	config := crawley.Config{
		MaxDepth:   1,
		MaxThreads: 3,
	}

	crawler := crawley.NewCrawler(config)

	// 设置数据提取器
	crawler.OnResponse(func(resp *crawley.Response) {
		// 使用CSS选择器提取标题
		title, err := resp.SelectText("title")
		if err != nil {
			log.Printf("Error extracting title: %v", err)
		} else {
			fmt.Printf("Page title: %s\n", title)
		}

		// 提取所有段落文本
		paragraphs, err := resp.SelectAllText("p")
		if err != nil {
			log.Printf("Error extracting paragraphs: %v", err)
		} else {
			fmt.Println("\nParagraphs:")
			for i, p := range paragraphs {
				fmt.Printf("%d: %s\n", i+1, p)
			}
		}

		// 提取链接和对应的文本
		links, err := resp.SelectAll("a", selector.Attr("href"), selector.Text())
		if err != nil {
			log.Printf("Error extracting links: %v", err)
		} else {
			fmt.Println("\nLinks:")
			for _, link := range links {
				fmt.Printf("%s -> %s\n", link[1], link[0])
			}
		}
	})

	fmt.Printf("Crawling %s for data...\n", url)
	crawler.Crawl(url)
}

高级功能:限速与持久化

Crawley还支持限速和结果持久化等高级功能:

package main

import (
	"encoding/json"
	"fmt"
	"log"
	"os"
	"time"

	"github.com/slyrz/crawley"
	"github.com/slyrz/crawley/filter"
	"github.com/slyrz/crawley/selector"
)

type PageData struct {
	URL    string   `json:"url"`
	Title  string   `json:"title"`
	Links  []string `json:"links"`
	Images []string `json:"images"`
}

func main() {
	if len(os.Args) < 2 {
		fmt.Println("Usage: go run main.go <url>")
		return
	}

	url := os.Args[1]

	config := crawley.Config{
		MaxDepth:      3,
		MaxThreads:   5,
		RequestDelay: 1 * time.Second, // 每个请求之间的延迟
		Timeout:      10 * time.Second,
	}

	crawler := crawley.NewCrawler(config)
	crawler.AddFilter(filter.NewDomainFilter(url))

	outputFile, err := os.Create("output.json")
	if err != nil {
		log.Fatal(err)
	}
	defer outputFile.Close()

	encoder := json.NewEncoder(outputFile)

	crawler.OnResponse(func(resp *crawley.Response) {
		title, _ := resp.SelectText("title")
		links, _ := resp.SelectAll("a", selector.Attr("href"))
		images, _ := resp.SelectAll("img", selector.Attr("src"))

		pageData := PageData{
			URL:    resp.URL,
			Title:  title,
			Links:  links,
			Images: images,
		}

		// 将数据写入JSON文件
		if err := encoder.Encode(pageData); err != nil {
			log.Printf("Error writing to file: %v", err)
		}

		fmt.Printf("Processed: %s (%d links, %d images)\n", 
			resp.URL, len(links), len(images))
	})

	crawler.OnError(func(err error, url string) {
		log.Printf("Error crawling %s: %v", url, err)
	})

	fmt.Printf("Starting advanced crawl of %s...\n", url)
	crawler.Crawl(url)
	fmt.Println("Crawl completed! Results saved to output.json")
}

命令行参数处理

为了使爬虫更灵活,我们可以使用Go的flag包来添加命令行参数:

package main

import (
	"flag"
	"fmt"
	"log"

	"github.com/slyrz/crawley"
	"github.com/slyrz/crawley/filter"
)

func main() {
	// 定义命令行参数
	url := flag.String("url", "", "URL to start crawling from")
	depth := flag.Int("depth", 2, "Maximum crawl depth")
	threads := flag.Int("threads", 5, "Number of concurrent threads")
	output := flag.String("output", "results.txt", "Output file path")
	
	flag.Parse()

	if *url == "" {
		fmt.Println("Please provide a starting URL with -url")
		return
	}

	config := crawley.Config{
		MaxDepth:   *depth,
		MaxThreads: *threads,
	}

	crawler := crawley.NewCrawler(config)
	crawler.AddFilter(filter.NewDomainFilter(*url))

	// 这里可以添加响应处理器和错误处理器
	// ...

	fmt.Printf("Starting crawl of %s with depth %d and %d threads...\n", 
		*url, *depth, *threads)
	crawler.Crawl(*url)
	fmt.Printf("Results saved to %s\n", *output)
}

总结

Crawley是一个功能强大且灵活的Go语言爬虫库,通过上面的示例,我们可以看到它提供了:

  1. 并发控制
  2. 深度控制
  3. URL过滤
  4. 数据提取(CSS选择器和XPath)
  5. 限速功能
  6. 错误处理
  7. 可扩展的处理器接口

你可以根据实际需求组合这些功能来构建各种复杂的爬虫应用。记得在使用爬虫时要遵守目标网站的robots.txt规则,并设置合理的请求间隔以避免给目标服务器造成过大负担。

回到顶部