几分钟后,Go crawler 在从输出通道中选择时停止

我写了一个简单的爬虫,看起来像这样:


type SiteData struct {

    // ...

}


func downloadURL(url string) (body []byte, status int) {

    resp, err := http.Get(url)


    if err != nil {

        return

    }


    status = resp.StatusCode

    defer resp.Body.Close()


    body, err = ioutil.ReadAll(resp.Body)

    body = bytes.Trim(body, "\x00")


    return

}



func processSiteData(resp []byte) SiteData {

    // ...

}    


func worker(input chan string, output chan SiteData) {


    // wait on the channel for links to process

    for url := range input {


        // fetch the http response and status code

        resp, status := downloadURL(url)


        if resp != nil && status == 200 {

            // if no errors in fetching link

            // process the data and send 

            // it back

            output <- processSiteData(resp)

        } else {

            // otherwise send the url for processing

            // once more

            input <- url

        }

    }

}


func crawl(urlList []string) {

    numWorkers := 4

    input := make(chan string)

    output := make(chan SiteData)


    // spawn workers

    for i := 0; i < numWorkers; i++ {

        go worker(input, output)

    }


    // enqueue urls

    go func() {

        for url := range urlList {

            input <- url

        }

    }()


    // wait for the results

    for {

        select {

        case data := <-output:

            saveToDB(data)

        }

    }


}


func main() {

    urlList := loadLinksFromDB()

    crawl(urlList)

}

它抓取单个网站并运行良好 - 下载数据,处理它并将其保存到数据库中。然而,几分钟(5-10)左右后,它会“卡住”,需要重新启动。该站点没有将我列入黑名单,我已经与他们进行了验证,并且可以在程序阻止后随时访问任何 url。此外,它会在所有 url 完成处理之前阻止。显然它会在列表用完时阻塞,但它远不及那个。


我在这里做错了吗?我使用for { select { ... } }而不是的原因for _, _ = range urlList { // read output }是,如果处理失败,任何 url 都可以重新排队。此外,数据库似乎也不是这里的问题。任何输入都会有所帮助 - 谢谢。


阿波罗的战车
浏览 184回答 1
1回答
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go