欢迎光临
我们一直在努力

go语言学习例子No.18-多页面单任务爬虫1

爬取第一页的全部链接里的下载地址包括下一页

继上一个例子,我们来改写一下

fetcher.go内容

package fetcher

import (
	"errors"
	"io/ioutil"
	"net/http"
)

func Fetch(url string) ([]byte, error) {
	client := &http.Client{}
	req, _ := http.NewRequest("GET", url, nil)
	req.Header.Set("User-Agent", "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)")
	res, err := client.Do(req)
	if err != nil {
		return nil, err
	}
	if res.StatusCode != 200 {
		return nil, errors.New("Wrong StatusCode!")
	}
	defer res.Body.Close()

	return ioutil.ReadAll(res.Body)
}

//我把URL请求的逻辑都放在了fetch函数中,里面做了一些异常处理。值得说的有2点:

//在Header中设置了User-Agent,让访问看起来更像搜索引擎Bot。如果一个网站希望自己的内容被Google收录那么他就不会拒绝这样的UA的访问。
//需要通过ioutil.ReadAll 读取res的body内容

types.goparser.go一个目录

package parser

type Request struct { //保存要爬取的url和对应的函数
	Url        string
	ParserFunc func([]byte) ParserResult
}

type ParserResult struct { //保存爬取的结果
	Requests []Request     //可以爬取到很多地址加到队列里
	Items    []interface{} //爬取到的项目名称
}

parser.go内容

package parser

import (
	"regexp"
)

const urlRe = `<h5><a target="_blank" href="([^"]+)">([^<]+)</a></h5>`
const mp4ListRe = `thurl="(http:\/\/[^"]+)"`
const nextPageRe = `<a target="_self" href="([^"]+)" class="pagelink_a">下一页</a>`

func Parse(contents []byte) ParserResult {
	rep := regexp.MustCompile(urlRe)                         //匹配正则
	match := rep.FindAllStringSubmatch(string(contents), -1) //返回字符串切片,-1表示全部,1表示匹配1个,2就匹配2个
	result := ParserResult{}                                 //新建一个队列
	for _, m := range match {                                //遍历字符串切片
		result.Items = append(result.Items, m[2]) //获取到匹配的名称加到Items里,m[2]代表正则里的第二个括号里的内容
		result.Requests = append(result.Requests, //获取到匹配的url加到队列里,m[1]代表正则里的第一个括号里的内容
			Request{
				Url:        "https://www.193291.com/" + m[1],
				ParserFunc: Parsemp4list, //这个队列里的函数是Parsemp4list
			})
	}
	result.Items = append(result.Items, "下一页") //获取到下一页的url加到队列里里
	result.Requests = append(result.Requests, ParseNextPage(contents))
	return result

}
func Parsemp4list(contents []byte) ParserResult {
	rep := regexp.MustCompile(mp4ListRe)                     //匹配正则
	match := rep.FindAllStringSubmatch(string(contents), -1) //返回字符串切片,-1表示全部,1表示匹配1个,2就匹配2个
	result := ParserResult{}                                 //新建一个队列
	for _, m := range match {
		result.Items = append(result.Items, m[1]) //获取到匹配的url加到队列里,m[1]代表正则里的第一个括号里的内容
		result.Requests = nil                     //这里获取到了下载地址就不用再添加队列
	}
	return result
}

func Nilparser([]byte) ParserResult {
	return ParserResult{}
}
func ParseNextPage(contents []byte) Request {
	rep := regexp.MustCompile(nextPageRe)             //匹配下一页的正则
	match := rep.FindStringSubmatch(string(contents)) //返回字符串切片
	return Request{
		Url:        "https://www.193291.com/" + match[1],
		ParserFunc: Parse, //这个队列里的函数是Parse
	}

}

engine.go内容

package engine

import (
	"fmt"
	"log"

	"crawler0.4/fetcher"
	"crawler0.4/parser"
)

func Run(seed parser.Request) { //参数是一个种子
	var requests []parser.Request     //新建一个队列接收种子
	requests = append(requests, seed) //接收参数传来的第一个种子
	for len(requests) > 0 {           //如果种子不位0
		r := requests[0]                      //取第一个种子
		requests = requests[1:]               //截掉第一个种子
		contents, err := fetcher.Fetch(r.Url) //开始爬取对应种子的页面
		if err != nil {
			log.Printf("Fetching %s error!", r.Url)
			continue //如果获取失败就继续下一个种子
		}
		parserResult := r.ParserFunc(contents)                //队列结构的函数提取结果
		requests = append(requests, parserResult.Requests...) //这里可以获取到很多url加到队列中
		for _, item := range parserResult.Items {
			fmt.Printf("Got item: %s \n", item) //打印队列里的项目
		}
		fmt.Printf("获取到%d条信息\n", len(parserResult.Items))

	}

}

main.go内容

package main

import (
	"crawler0.4/engine"
	"crawler0.4/parser"
)

func main() {
	engine.Run(parser.Request{
		Url:        "https://www.193291.com/index.php?m=vod-list-id-4-order--by-time-class-0-year-0-letter--area--lang-.html",
		ParserFunc: parser.Parse,
	})

}

这样就一直获取到url包括下一页,加到队列里爬取下载地址,但不是并发,一个一个获取的,下次改成并发

 收藏 (0) 打赏

您可以选择一种方式赞助本站

支付宝扫一扫赞助

微信钱包扫描赞助

未经允许不得转载:家里蹲的狐狸 » go语言学习例子No.18-多页面单任务爬虫1

分享到: 生成海报
avatar

评论 抢沙发

  • QQ号
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

登录

忘记密码 ?

切换登录

注册

我们将发送一封验证邮件至你的邮箱, 请正确填写以完成账号注册和激活