当前位置:   article > 正文

go语言简单的爬取网站信息(上)_golang get请求网页获取content

golang get请求网页获取content

基本流程

首先根据url,获取网站的html信息,然后提取出所需的内容

因为网页的编码方式不同,有的中文会编程乱码,所以需要转码
另外提取内容,需要使用正则表达式来匹配

转码

引用包
go get golang.org/x/text
使用transform.NewReader新建一个utf8编码的Reader,需要参数io.Reader和网页原本的编码格式
如果网页是GBK编码,可以直接转

//这里resp为使用http.Get("url地址")获取到的,resp.body为一个Reader
utf8Reader := transform.NewReader(resp.body,simplifiedchinese.GBK.NewDecoder())
  • 1
  • 2

但如果不知道原网页是什么编码格式,就需要识别一下
引用包
go get golang.org/x/net/html
使用charset.DetermineEncoding方法获取编码格式

//取出原本Reader的前1024个字节新建一个Reader,然后识别
r,_ := bufio.NewReader(resp.body).Peek(1024)
//当网页编码格式为GBK时,这里的e就相当于之前的simplifiedchinese.GBK
e := charset.DetermineEncoding(r,"")
  • 1
  • 2
  • 3
  • 4

正则表达式

使用regexp.Compile来匹配

格式
.代表任意字符
*代表0到多个
+代表1到多个
[a-z]代表所有小写字母
[A-Z]代表所有大写字母
[0-9]代表所有数字
[^>]代表不为>的字符
[\s]代表任意空白字符

const origen string = "原始内容"
const content string = `匹配内容`
//如果能够确保匹配到,可以使用MustCompile方法
r,_ := regexp.Compile(content)
//FindAll传入的是[]byte,返回的是[][]byte,如果想要string,可以使用FindAllString
m := r.FindAll(origen,-1)
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

具体实现

首先需要根据url获取网页内容,可以将这一部分封装到一个包中

package fetcher
import (
	"bufio"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"net/http"

	"golang.org/x/net/html/charset"
	"golang.org/x/text/encoding"
	"golang.org/x/text/encoding/unicode"
	"golang.org/x/text/transform"
)
//获取网页内容的函数
func Fetch(url string) ([]byte,error){
	resp,err := http.Get(url)
	if err != nil{
		return nil,err
	}
	defer resp.body.Close()
	if resp.StatusCode != http.StatusOK{
		return nil,fmt.Errorf("fetch error no statusok")
	}
	//获取网页编码格式
	e := determineEncoding(resp.body)
	utf8Reader :=  transform.NewReader(resp.body,e.NewDecoder())
	b,err := ioutil.ReadAll(utf8Reader)
	if err != nil{
		return nil,err
	}
	return b,nil
}

func determineEncoding(i io.Reader) encoding.Encoding{
	//先取出前1024个自己新建一个Reader
	re,err := bufio.NewReader(i).Peek(1024)
	if err != nil{
		log.Printf("error : %v",err)
		return unicode.UTF8
	}
	//获取Reader的编码格式
	e,_,_ := charset.DetermineEncoding(re,"")
	return e
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45

然后需要定义一些类型,来存储入参和出参
提取网页内容的函数返回结果是一个url和一个内容,这个url还会继续被用来爬取,但是提取方法不一样,因此可以将返回结果的属性设为一个requests和一个items,request中又包括url和具体的提取方法parseFunc

package engine

type Request struct{
	URL string
	ParseFunc func(content []byte) ParseResult
}

type ParseResult struct{
	Requests []Request
	//[]interface{}代表任意类型
	Items []interface{}
}

//这里是一个空的提取方法,因为这篇文章只会先写第一层的提取方法,所以在进行下一层提取时,先传一个空的提取方法
func NilParseFunc(content []byte) ParseResult{
	return ParseResult{}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

第一层提取方法的实现

package parser

const con string = `<a href="([^"]*)"[\s][^>]*>([^<]*)`

func ParseCityList(content []byte) engine.ParseResult{
	r,_ := regexp.Compile(con)
	m := r.FindAll(content,-1)
	var result engine.ParseResult
	for _,mm := range m{
		//这里使用string(mm[2]),是为了后面打印出来直接可以用%s
		result.Items = append(result.Items,string(mm[2]))
		result.Requests = append(result.Requests,engine.Request{mm[1],engine.NilParseFunc})
	}
	return result
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15

具体的运行方法

package engine

func Run(seeds ...Request){
	var requests []Request
	for s := range seeds{
		requests = append(requests,s)
	}
	for len(requests) > 0{
		r := requests[0]
		requests = requests[1:]
		b,_ := fetcher.Fetch(r.URL)
		result := r.ParseFunc(b)
		for _,m := range result.Items{
			fmt.Printf("%s\n",m)
		}
	}
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17

在main函数中直接调用运行方法Run

package main

const url string = "localhost:8080/zhenai"

func main(){
	engine.Run(engine.Request{url,parser.ParserCityList})
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/607746
推荐阅读
相关标签
  

闽ICP备14008679号