go语言简单的爬取网站信息(下)

go语言简单的爬取网站信息(下)

之前的内容已经写好了获取网站内容的函数fetch,爬取第一层城市列表的解析器ParseCityList函数,以及实际爬取的函数Run(传入种子,包含url和解析器,根据url,调用解析器解析)

基本的框架就是这样,后面只需要再分别写不同的解析器就好了

城市解析器

//首先写好匹配的正则表达式
citys := `([^<]+)`
func ParseCity(content []byte) engine.ParseResult{
    cityRe := regexp.Compile(citys)
    var result = engine.ParseResult{}
    b := cityRe.FindAllStringSubmatch(string(content),-1)
    for bb := range b{
        result.Item = append(result.Item,bb[1])
        //这里ParseProfile是下一层的解析器,实际上之前城市列表解析器的这里应该改成该解析器ParseCity
        result.Requests = append(result.Requests,engine.Request{URL:bb[0] PaserFunc:ParseProfile})
    }
    return result
}

用户解析器

因为用户的信息是我们爬取信息的根本目的,信息比较丰富,所以我们需要单独定义一个结构体来存储用户的信息

package models

type Profiles struct {
	Name               string
	Age                int
	Height             int
	Weight             int
	Income             string
	MerrageState       string
	EducationSituation string
	Profession         string
	JiGuan             string
	Sex                string
	Xingzuo            string
	Housing            string
	Caring             string
	ExpectSize         string
}

具体的用户解析器

//因为要解析的内容比较多,先将*regexp赋好值
var ageRe := regexp.Compile(`年龄:([0-9]+)岁`)
var heightRe, _ = regexp.Compile(`身高:([0-9^C]+)CM`)
var weightRe, _ = regexp.Compile(`体重:([0-9^K]+)KG`)
var incomeRe, _ = regexp.Compile(`月收入:([^<]+)`)
var merrageStateRe, _ = regexp.Compile(`婚况:([^<]+)`)
var educationSituationRe, _ = regexp.Compile(`学历:([^<]+)`)
var xingzuoRe, _ = regexp.Compile(`星座:([^<]+)`)
var professionRe, _ = regexp.Compile(`职业:([^<]+)`)
var jiGuanRe, _ = regexp.Compile(`籍贯:([^<]+)`)
var sexRe, _ = regexp.Compile(`性别:([^<]+)`)
var housingRe, _ = regexp.Compile(`住房条件:([^<]+)`)
var caringRe, _ = regexp.Compile(`是否购车:([^<]+)`)
var expectSizeRe, _ = regexp.Compile(`体型:([^<]+)`)

//直接定义一个函数返回匹配到的内容
func Get(reg *regexp.Regexp,content []byte) string{
	//因为只取一个值,所以不使用findall函数了
	m := reg.FindStringSubmatch(content)
	if len(m) >= 1{
		//m[0]匹配到的是整个内容,m[1]是括起来的内容,也就是具体的用户信息
		return m[1]
	}else{
		return ""
	}
}

//解析器
//这里多出一个参数,接收上一层传过来的名字,但就不符合定义好的解析器函数类型了
//所以在上一层解析器中需要修改一下,创建一个匿名函数,然后在其中调用该函数
func ParseProfile(content []byte,name string)engine.ParseResult{
	//定义一个实体用来接收数据
	var profile models.Profiles
	//对于想要整数型的数据,转一下类型
	age,err := strconv.Atoi(Get(content,ageRe))
	if err != nil{
		age = 0
	}
	height,err := strconv.Atoi(Get(content,heightRe))
	if err != nil{
		height = 0
	}
	weight, err := strconv.Atoi(Get(weightRe, content))
	if err != nil {
		weight = 0
	}
	profile.Name = name
	profile.Age = age
	profile.Height = height
	profile.Weight = weight
	profile.Income = Get(incomeRe, content)
	profile.MerrageState = Get(merrageStateRe, content)
	profile.EducationSituation = Get(educationSituationRe, content)
	profile.Xingzuo = Get(xingzuoRe, content)
	profile.Profession = Get(professionRe, content)
	profile.JiGuan = Get(jiGuanRe, content)
	profile.Sex = Get(sexRe, content)
	profile.Housing = Get(housingRe, content)
	profile.Caring = Get(caringRe, content)
	profile.ExpectSize = GetSecondTixing(expectSizeRe, content)
	var result engine.ParseResult
	result.Item = append(result.Item, profile)
	return result
}

//对于有多个相似内容的情况下,想要只取最后一个,新定义一个函数
func GetSecondTixing(reg *regexp.Regexp, content []byte) string {
	m := reg.FindAllStringSubmatch(string(content), -1)
	if len(m) >= 2 {
		if len(m[len(m)-1]) >= 2 {
			return m[len(m)-1][1]
		}
		return ""
	} else {
		return ""
	}
}

//修改一下上层解析器
citys := `([^<]+)`
func ParseCity(content []byte) engine.ParseResult{
    cityRe := regexp.Compile(citys)
    var result = engine.ParseResult{}
    b := cityRe.FindAllStringSubmatch(string(content),-1)
    for bb := range b{
        result.Item = append(result.Item,bb[1])
        //这里修改了一下,创建了个匿名函数,里面调用用户解析器的函数
        result.Requests = append(result.Requests,engine.Request{URL:bb[0] PaserFunc:func(content []byte)engine.ParseResult{return ParseProfile(content,bb[1])}})
    }
    return result
}

至此,简单的爬取网站就基本实现了。

你可能感兴趣的:(爬虫,go语言,golang,python,前端)