赞
踩
首先根据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())
但如果不知道原网页是什么编码格式,就需要识别一下
引用包
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,"")
使用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)
首先需要根据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 }
然后需要定义一些类型,来存储入参和出参
提取网页内容的函数返回结果是一个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{} }
第一层提取方法的实现
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
}
具体的运行方法
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) } } }
在main函数中直接调用运行方法Run
package main
const url string = "localhost:8080/zhenai"
func main(){
engine.Run(engine.Request{url,parser.ParserCityList})
}
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。