我写了一个简单的爬虫,看起来像这样:
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 都可以重新排队。此外,数据库似乎也不是这里的问题。任何输入都会有所帮助 - 谢谢。
相关分类