在 Golang 中使用 curl 在网站上搜索字符串最有效和可扩展的等价物是什么?

What is the most efficient and scalable equivalent of grepping a string on a website using curl in Golang?

背景

user@host curl -s http://whosebug.com | grep -m 1 whosebug.com
如果找到字符串,立即

returns:

<meta name="twitter:domain" content="whosebug.com"/>

瞄准

使用 Golang 在网站上查找字符串

方法

基于 Go by Example and Schier's Blog 的来源,创建了以下代码:

package main

import (
    "fmt"
    "io/ioutil"
    "net/http"
    "regexp"
)

func main() {
    url := "http://whosebug.com"
    resp, _ := http.Get(url)
    bytes, _ := ioutil.ReadAll(resp.Body)
    r, _ := regexp.Compile("whosebug.com")
    fmt.Println(r.FindString(string(bytes)))
    resp.Body.Close()
}

结果

运行 代码结果为:

whosebug.com

讨论与结论

  1. 需要更多代码才能在 Golang 中实现相同的目标,或者是否有更短的解决方案
  2. 这两个选项似乎同时return。在这种情况下,静态代码是否也比动态代码更快?
  3. 我担心这段代码是不是太耗内存了。它最终应该被用来监控数百个不同的网站

此代码实现 grep,在包含给定字符串的第一行停止。它通过使用 bufio.Scanner 避免一次将整个网页读入内存,这除了限制内存使用外还可能在字符串位于大页面开头附近的情况下加速程序。小心使用 scan.Bytes() 以避免将每一行都转换为字符串,这会导致显着的内存流失。

package main

import (
    "bufio"
    "bytes"
    "fmt"
    "log"
    "net/http"
)

func main() {
    resp, err := http.Get("http://whosebug.com")
    if err != nil {
        log.Fatalf("failed to open url")
    }
    scan := bufio.NewScanner(resp.Body)
    toFind := []byte("whosebug.com")
    defer resp.Body.Close()
    for scan.Scan() {
        if bytes.Contains(scan.Bytes(), toFind) {
            fmt.Println(scan.Text())
            return
        }
    }
}