如何解决for死循环阻塞问题?

来源:16-7 更多用户与去重

slkk

2020-06-10

在学习爬虫的时候,需要进行分页爬取,于是我就提前访问了一次以便获取相应页的总页数,使用了goroutines,但是爬取效率反而变慢了,还出现卡死的情况,谁能帮我看看是怎么回事?

获取城市代码:

package parser

import (
	"crawler/engine"
	"crawler/fetcher"
	"fmt"
	"github.com/PuerkitoBio/goquery"
	"log"
	"regexp"
	"strconv"
	"strings"
)

var numRe = regexp.MustCompile(`\d+`)

func ParseCity(contents []byte) engine.ParseResult {

	dom, err := goquery.NewDocumentFromReader(strings.NewReader(string(contents)))
	if err != nil {
		log.Fatalln(err)
	}
	var list []string
	dom.Find(".groupForum .topicTitle").Each(func(i int, selection *goquery.Selection) {
		_, exists := selection.Attr("span")
		var (
			href string
			e    bool
		)
		if exists {
			href, e = selection.Find(".topicTitleSelf a").Attr("href")
		} else {
			href, e = selection.Find("a").Attr("href")
		}

		if e {
			list = append(list, href)
		}
	})

	arr := make(chan map[string]string, 100)
	flag := make(chan bool, 1)
	for _, uri := range list {
		go func(uri string) {
			contents, err := fetcher.Fetch(uri)
			if err != nil {
				flag <- false
			}
			//获取分页
			doc, err := goquery.NewDocumentFromReader(strings.NewReader(string(contents)))
			if err != nil {
				flag <- false
			}
			size := dom.Find(".pagejump").Size()

			total := 1
			if size > 1 {
				var page string
				doc.Find(".page-number").Each(func(i int, selection *goquery.Selection) {
					page = selection.Text()
				})
				total, _ = strconv.Atoi(numRe.FindString(page))
			}
			arr <- map[string]string{"total": strconv.Itoa(total), "href": uri}
		}(uri)
	}

	var r = make(chan engine.ParseResult,100)
	go func() {
		for {
			select {
			case f := <-flag:
				if !f {
					continue
				}
			case body := <-arr:
				var result engine.ParseResult
				//t, _ := strconv.Atoi(body["total"])
				u := body["href"]
				result.Requests = append(result.Requests, engine.Request{
					Url: u,
					//ParseFunc: func(contents []byte) engine.ParseResult {
					//	return ParseProfile(contents, u, t)
					//},
				})
			}
		}
	}()

	for {
		select {
		case result:= <-r:
			fmt.Printf("城市:%+v\n\r",result)
			return result
		}
	}

}

是否是for循环一直在等待的原因?如果是,应该怎么处理呢?

写回答

2回答

ccmouse

2020-06-10

似乎并没有人会给r送数据

1
1
slkk
非常感谢!
2020-06-11
共1条回复

slkk

提问者

2020-06-11

感谢老师回答,给r送数据我是有写的,只是贴代码的时候在修改,所以漏掉了。我这种写法有点问题,我后面修改了,可以根据老师的架构在创建一个方法专门去获取总页数和进行分页,然后把请求链接继续放进request队列里面去,这样就不必再写单独的协程方法去获取总分页。


0
1
尼克2018
可以分享你的写 法
2021-01-17
共1条回复

Google资深工程师深度讲解Go语言 由浅入深掌握Go语言

语法+分布式爬虫实战 为转型工程师量身打造

5995 学习 · 1909 问题

查看课程