首页 文章资讯内容详情

golang并发爬虫

2026-06-01 5 花语

爬虫的需求很简单,就是从paste.ubuntu.com上搞别人贴的代码,然后判断是不是C/C++代码。面临着几个问题需要考虑:

1、paste访问的时间很长,这很影响爬虫和内容处理的效率,这该怎么办:

这个问题我使用了三种方法来解决,第一个是采用并行程序,这个就不多说了,多开几个线程做处理会快些。第二个是预判这个文件的大小,设定一个阈值,保证这个文件超过阈值后一定不是C/C++的题解代码,当然塞一张表除外,不过OJ一般限制65535B,我们可以取一半即30000B。第三个是设置timeout,在golang里就需要手工建立一个client发送get请求了,这里的具体函数如下:

funcGetHtml(Urlstring,MagicNumstring)[]byte{ timeout:=time.Duration(15*time.Second) client:=http.Client{ Timeout:timeout, } request,err:=http.NewRequest(http.MethodGet,Url,nil) iferr!=nil{ log.Errorln(err.Error()) returnnil } res,err:=client.Do(request) iferr!=nil{ log.Errorln(err.Error()) returnnil } result,err:=ioutil.ReadAll(res.Body) iflen(result)>30000{ returnnil } res.Body.Close() iferr!=nil{ log.Errorln(err.Error()) returnnil } rd:=bytes.NewReader(result) nd,err:=goquery.Parse(rd) iferr!=nil{ log.Panicln(err.Error()) } str:=nd.Find("td.code").Text() buf:=[]byte(str) returnbuf }

GetHtml

2、判断这个html中包含的代码是C/C++代码:

这个我处理得很糙,就是去看看有没有一个#include子串,当然这个子串是可以增加的,不过可能影响效率。希望有更好办法的朋友可以留下你的方法,在此谢谢。

funcJudge(buf[]byte)bool{ varpatterns=[]string{ "#include", } n:=len(patterns) fori:=0;i<n;i++{ ok,err:=regexp.Match(patterns[i],buf) ifok{ returntrue } iferr!=nil{ log.Errorln(err.Error()) returnfalse } } returnfalse }

Judge

3、并行访问时如何保证访问不冲突:

这个也很好解决,学过操作系统的人都明白可以添加一个mutex来保证一个资源不被同时访问。我这里更新的是一个offset,道理是一样的。这个os.Args[1]和offset都是全局变量,但是只有offset需要写,所以只给它加mutex就行了。

funcnumGetter(MagicNumstring,chchanint64){ Num,err:=strconv.ParseInt(MagicNum,10,64) iferr!=nil{ log.Errorln(err.Error()) return } ch<-(Num+Offset) Offset++ }

numGetter

funcNumGetter(Numstring,chchanint64){ for{ mutex.Lock() numGetter(Num,ch) mutex.Unlock() Do(strconv.FormatInt(<-ch,10)) } }

最后并行程序,一个go就可以解决~os.Args[2]用于设定线程数。

funcmain(){ Offset=0 ch:=make(chanint64,10) n,err:=strconv.ParseInt(os.Args[2],10,64) iferr!=nil{ log.Errorln(err.Error()) return } variint64 fori=0;i<n;i++{ goNumGetter(os.Args[1],ch) } time.Sleep(time.Hour) }

这是我第一次尝试用golang写并行的爬虫程序。我从学习写golang到现在有半个月的时间了,是时候找一本书认真学习一下go这个美妙的语言了。现在写的程序都是在翻译自己脑子里用其他语言写好的程序而已,我应该更多地去使用go语言的特性才可以。

原文链接: