内容简介:一、以下参考如果大家以前做过前端开发,对jquery不会陌生,goquery类似jquery,它是jquery的go版本实现。使用它,可以很方便的对HTML进行处理。
package main import ( "fmt" "io/ioutil" "net/http" "regexp" "time" "os" "strconv" ) //定义新的数据类型 type Spider struct { url string header map[string]string } //定义 Spider get的方法 func (keyword Spider) get_html_header() string { client := &http.Client{} req, err := http.NewRequest("GET", keyword.url, nil) if err != nil { } for key, value := range keyword.header { req.Header.Add(key, value) } resp, err := client.Do(req) if err != nil { } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { } return string(body) } func parse() { header := map[string]string{ "Host": "movie.douban.com", "Connection": "keep-alive", "Cache-Control": "max-age=0", "Upgrade-Insecure-Requests": "1", "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.143 Safari/537.36", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Referer": "https://movie.douban.com/top250", } //创建excel文件 f, err := os.Create("D:/haha3.txt") if err != nil { panic(err) } defer f.Close() //写入标题 f.WriteString("电影名称"+"\t"+"评分"+"\t"+"评价人数"+"\t"+"\r\n") //循环每页解析并把结果写入excel for i:=0;i<10;i++{ fmt.Println("正在抓取第"+strconv.Itoa(i)+"页......") url:="https://movie.douban.com/top250?start="+strconv.Itoa(i*25)+"&filter=" spider := &Spider{url, header} html := spider.get_html_header() //评价人数 pattern2:=`<span>(.*?)评价</span>` rp2 := regexp.MustCompile(pattern2) find_txt2 := rp2.FindAllStringSubmatch(html,-1) //评分 pattern3:=`property="v:average">(.*?)</span>` rp3 := regexp.MustCompile(pattern3) find_txt3 := rp3.FindAllStringSubmatch(html,-1) //电影名称 pattern4:=`alt="(.*?)" src="` rp4 := regexp.MustCompile(pattern4) find_txt4 := rp4.FindAllStringSubmatch(html,-1) // 写入UTF-8 BOM f.WriteString("\xEF\xBB\xBF") // 打印全部数据和写入excel文件 for i:=0;i<len(find_txt2);i++{ fmt.Printf("%s %s %s\n",find_txt4[i][1],find_txt3[i][1],find_txt2[i][1], ) f.WriteString(find_txt4[i][1]+"\t"+find_txt3[i][1]+"\t"+find_txt2[i][1]+"\t"+"\r\n") } } } func main() { t1 := time.Now() // get current time parse() elapsed := time.Since(t1) fmt.Println("爬虫结束,总共耗时: ", elapsed) }
二、goquery
上面第一部分的例子,使用了正则表达式来匹配,使用goquery会更方便。goquery是一个使用 go 语言写成的HTML解析库,可以让你像jQuery那样的方式来操作DOM文档。
获取代码:
gopm get -g github.com/PuerkitoBio/goquery
直接使用go get方式安装失败,这里使用了gopm来安装,关于gopm可以参考 国内的go get问题的解决 --gopm
在代码中引用时:
import “github.com/PuerkitoBio/goquery”
以下参考 golang goquery selector(选择器) 示例大全
如果大家以前做过前端开发,对jquery不会陌生,goquery类似jquery,它是jquery的go版本实现。使用它,可以很方便的对HTML进行处理。
1.基于HTML Element 元素的选择器
这个比较简单,就是基于a,p等这些HTML的基本元素进行选择,这种直接使用Element名称作为选择器即可。比如dom.Find("div")。
func findDiv() { html := `<body> <div>DIV1</div> <div>DIV2</div> <span>SPAN</span> </body> ` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find("div").Each(func(i int, selection *goquery.Selection) { fmt.Println("i",i,"select text",selection.Text()) }) }
2.ID 选择器
这个是使用频次最多的,类似于上面的例子,有两个div元素,其实我们只需要其中的一个,那么我们只需要给这个标记一个唯一的id即可,这样我们就可以使用id选择器,精确定位了。
func main() { html := `<body> <div id="div1">DIV1</div> <div>DIV2</div> <span>SPAN</span> </body> ` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find("#div1").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) }
3.Element ID 选择器
id选择器以#开头,紧跟着元素id的值,使用语法为dom.Find(#id),后面的例子我会简写为Find(#id),大家知道这是代表goquery选择器的即可。
如果有相同的ID,但是它们又分别属于不同的HTML元素怎么办?有好办法,和Element结合起来。比如我们筛选元素为div,并且id是div1的元素,就可以使用Find(div#div1)这样的筛选器进行筛选。
所以这类筛选器的语法为Find(element#id),这是常用的组合方法,比如后面讲的过滤器也可以采用这种方式组合使用。
4.Class选择器
class也是HTML中常用的属性,我们可以通过class选择器来快速的筛选需要的HTML元素,它的用法和ID选择器类似,为Find(".class")。
func main() { html := `<body> <div id="div1">DIV1</div> <div class="name">DIV2</div> <span>SPAN</span> </body> ` dom,err:=goquery.NewDocumentFromReader(strings.NewReader(html)) if err!=nil{ log.Fatalln(err) } dom.Find(".name").Each(func(i int, selection *goquery.Selection) { fmt.Println(selection.Text()) }) }
以上示例中,就筛选出来class为name的这个div元素。
5.Element Class 选择器
class选择器和id选择器一样,也可以结合着HTML元素使用,他们的语法也类似Find(element.class),这样就可以筛选特定element、并且指定class的元素。
三、使用goquery爬取豆瓣电影top250
package main import ( "net/http" "fmt" "github.com/PuerkitoBio/goquery" "strconv" ) func GetMovie(url string) { fmt.Println(url) resp, err := http.Get(url) if err != nil { panic(err) } //bodyString, err := ioutil.ReadAll(resp.Body) //fmt.Println(string(bodyString)) if resp.StatusCode != 200 { fmt.Println("err") } doc, err := goquery.NewDocumentFromReader(resp.Body) if err != nil { panic(err) } // doc.Find("#content h1").Each(func(i int, s *goquery.Selection) { // name fmt.Println("name:" + s.ChildrenFiltered(`[property="v:itemreviewed"]`).Text()) // year fmt.Println("year:" + s.ChildrenFiltered(`.year`).Text()) }) // #info > span:nth-child(1) > span.attrs director := "" doc.Find("#info span:nth-child(1) span.attrs").Each(func(i int, s *goquery.Selection) { // 导演 director += s.Text() //fmt.Println(s.Text()) }) fmt.Println("导演:" + director) //fmt.Println("\n") pl := "" doc.Find("#info span:nth-child(3) span.attrs").Each(func(i int, s *goquery.Selection) { pl += s.Text() }) fmt.Println("编剧:" + pl) charactor := "" doc.Find("#info span.actor span.attrs").Each(func(i int, s *goquery.Selection) { charactor += s.Text() }) fmt.Println("主演:" + charactor) typeStr := "" doc.Find("#info > span:nth-child(8)").Each(func(i int, s *goquery.Selection) { typeStr += s.Text() }) fmt.Println("类型:" + typeStr) } func GetToplist(url string) []string { var urls []string resp, err := http.Get(url) if err != nil { panic(err) } //bodyString, err := ioutil.ReadAll(resp.Body) //fmt.Println(string(bodyString)) if resp.StatusCode != 200 { fmt.Println("err") } doc, err := goquery.NewDocumentFromReader(resp.Body) if err != nil { panic(err) } doc.Find("#content div div.article ol li div div.info div.hd a"). Each(func(i int, s *goquery.Selection) { // year fmt.Printf("%v", s) herf, _ := s.Attr("href") urls = append(urls, herf) }) return urls } func main() { url := "https://movie.douban.com/top250?start=" var urls []string var newUrl string fmt.Println("%v", urls) for i := 0; i < 10; i++ { start := i * 25 newUrl = url + strconv.Itoa(start) urls = GetToplist(newUrl) for _, url := range urls { GetMovie(url) } } }
注意这个Find: doc.Find("#content div div.article ol li div div.info div.hd a")
,参考返回的html内容,这里是个多层查找,#是查找id,带点的是找相应的class。当然改成 doc.Find("ol.grid_view li div.hd a")
也是可以的。最终都是要找列表里的li,然后挑出href
以上所述就是小编给大家介绍的《Golang 爬虫》,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对 码农网 的支持!
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Windows高级调试
Mario Hewardt、Daniel Pravat / 聂雪军 / 机械工业出版社 / 2009-5 / 79.00元
本书主要讲解Windows高级调试思想和工具,并涉及一些高级调试主题。本书内容主要包括:工具简介、调试器简介、调试器揭密、符号文件与源文件的管理、栈内存破坏、堆内存破坏、安全、进程间通信、资源泄漏、同步、编写定制的调试扩展、64位调试、事后调试、Windows Vista基础以及应用程序验证器的测试设置等。本书内容详实、条理清楚。 本书适合Windows开发人员、Windows测试人员和Windo......一起来看看 《Windows高级调试》 这本书的介绍吧!