NewCollector(options …func(Collector)) Collector

创建一个默认配置的新collector实例。

  1. func NewCollector(options ...func(*Collector)) *Collector {
  2. c := &Collector{}
  3. c.Init()
  4. for _, f := range options {
  5. f(c)
  6. }
  7. c.parseSettingsFromEnv()
  8. return c
  9. }

Collector Struct

  1. // Collector 为采集工作提供采集实例
  2. type Collector struct {
  3. // UserAgent 是 User-Agent 字符串,用于 HTTP request
  4. UserAgent string
  5. // MaxDepth 限制访问URLs递归深度。
  6. // 关于无限递归设置它为0(默认)
  7. MaxDepth int
  8. // AllowDomains 是一个域名白名单。
  9. // 为空的话,表示可访问任何域名。
  10. AllowedDomains []string
  11. // DisallowedDomains 是一个域名黑名单。
  12. DisallowedDomains []string
  13. // DisallowedURLFilters 是一个正则表达式列表,它限制访问URLs。
  14. // 如果匹配到了URL,请求将被终止。
  15. // DiallowedURLFilters 在 URLFilters为空允许任何URLs访问之前进行评估。
  16. DisallowedURLFilters []*regexp.Regexp
  17. //URLFilters是一个限制访问URl的正则表达式列表。如果结果集中的任意一个匹配到的URl将被终止请求。
  18. //DiallowedURLFilters在URLFilters之前执行。
  19. //为空,则允许任何URLs被访问。
  20. URLFilters []*regexp.Regexp
  21. // AllowURLRevisit 允许多次下载同一个URL
  22. AllowURLRevisit bool
  23. // MaxBodySize 是限制response body字节大小
  24. // 0 表示没有限制。
  25. // MaxBodySize默认值是10MB(10 * 1024 * 1024 bytes)。
  26. MaxBodySize int
  27. // CacheDir 指定一个缓存GET请求缓存文件的存储地址。
  28. // 当它没有定义,则缓存不可用。
  29. CacheDir string
  30. // IgnoreRobotsTxt 允许 Collector忽略主机robots.txt文件中的规则。更多信息参见 http://www.robotstxt.org/
  31. IgnoreRobotsTxt bool
  32. // Async 启动异步网络通信。使用Collector.Wait()来确认所有请求都已经完成。
  33. Async bool
  34. // ParseHTTpErrorResponse 允许解析非2xx状态码的HTTP。
  35. // 默认,Colly只解析成功的HTTP响应。ParseHTTPErrorResponse 设置true开启它。
  36. ParseHTTPErrorResponse bool
  37. // ID是一个collector的唯一标识。
  38. ID uint32
  39. // 可以为非utf8响应体启用字符编码检测,而无需显式的字符集声明。该特性使用 https://github.com/saintfish/chardet
  40. DetectCharset bool
  41. // RedirectHandler 允许控制如何管理重定向
  42. RedirectHandler func(req *http.Request, via []*http.Request) error
  43. // CheckHead 每个GET预先验证响应之前执行一个HEAD请求。
  44. CheckHead bool
  45. store storage.Storage
  46. debugger debug.Debugger
  47. robotsMap map[string]*robotstxt.RobotsData
  48. htmlCallbacks []*htmlCallbackContainer
  49. xmlCallbacks []*xmlCallbackContainer
  50. requestCallbacks []RequestCallback
  51. responseCallbacks []ResponseCallback
  52. errorCallbacks []ErrorCallback
  53. scrapedCallbacks []ScrapedCallback
  54. requestCount uint32
  55. responseCount uint32
  56. backend *httpBackend
  57. wg *sync.WaitGroup
  58. lock *sync.RWMutex
  59. }

func(c *Collector) Init()

初始化 Collector 私有变量、集合和Collector 默认配置。

  1. func (c *Collector) Init() {
  2. c.UserAgent = "colly - https://github.com/gocolly/colly"
  3. c.MaxDepth = 0
  4. c.store = &storage.InMemoryStorage{}
  5. c.store.Init()
  6. c.MaxBodySize = 10 * 1024 * 1024
  7. c.backend = &httpBackend{}
  8. jar, _ := cookiejar.New(nil)
  9. c.backend.Init(jar)
  10. c.backend.Client.CheckRedirect = c.checkRedirectFunc()
  11. c.wg = &sync.WaitGroup{}
  12. c.lock = &sync.RWMutex{}
  13. c.robotsMap = make(map[string]*robotstxt.RobotsData)
  14. c.IgnoreRobotsTxt = true
  15. c.ID = atomic.AddUint32(&collectorCounter, 1)
  16. }

func (c *Collector) Visit(URL string) error

Visit通过创建对参数中指定的URL的请求来启动Collector的收集作业。Visit还调用前面提供的回调。

  1. func (c *Collector) Visit(URL string) error {
  2. if c.CheckHead {
  3. if check := c.scrape(URL, "HEAD", 1, nil, nil, nil, true); check != nil {
  4. return check
  5. }
  6. }
  7. return c.scrape(URL, "GET", 1, nil, nil, nil, true)
  8. }

func (c Collector) scrape(u, method string, depth int, requestData io.Reader, ctx Context, hdr http.Header, checkRevisit bool) error

  1. func (c *Collector) scrape(u, method string, depth int, requestData io.Reader, ctx *Context, hdr http.Header, checkRevisit bool) error {
  2. if err := c.requestCheck(u, method, depth, checkRevisit); err != nil {
  3. return err
  4. }
  5. parsedURL, err := url.Parse(u)
  6. if err != nil {
  7. return err
  8. }
  9. if parsedURL.Scheme == "" {
  10. parsedURL.Scheme = "http"
  11. }
  12. if !c.isDomainAllowed(parsedURL.Host) {
  13. return ErrForbiddenDomain
  14. }
  15. if method != "HEAD" && !c.IgnoreRobotsTxt {
  16. if err = c.checkRobots(parsedURL); err != nil {
  17. return err
  18. }
  19. }
  20. if hdr == nil {
  21. hdr = http.Header{"User-Agent": []string{c.UserAgent}}
  22. }
  23. rc, ok := requestData.(io.ReadCloser)
  24. if !ok && requestData != nil {
  25. rc = ioutil.NopCloser(requestData)
  26. }
  27. req := &http.Request{
  28. Method: method,
  29. URL: parsedURL,
  30. Proto: "HTTP/1.1",
  31. ProtoMajor: 1,
  32. ProtoMinor: 1,
  33. Header: hdr,
  34. Body: rc,
  35. Host: parsedURL.Host,
  36. }
  37. setRequestBody(req, requestData)
  38. u = parsedURL.String()
  39. c.wg.Add(1)
  40. if c.Async {
  41. go c.fetch(u, method, depth, requestData, ctx, hdr, req)
  42. return nil
  43. }
  44. return c.fetch(u, method, depth, requestData, ctx, hdr, req)
  45. }