手摸手教你用go写爬虫之二(准备知识:正则解析有效信息)

栏目: Go · 发布时间: 5年前

内容简介:本文介绍正则提取字符串中的相关信息字符串中的信息提取我们使用假设有一段html代码如下

本文介绍正则提取字符串中的相关信息

1. 正则

字符串中的信息提取我们使用 regexp 包的相关函数来解决

假设有一段html代码如下

<a
                                target="_blank"
                                title="钱江国际商务中心蛋壳公寓直租 月付无压力 无 南星"
                                _soj="Filter_56&hfilter=filterlist"
                                href="https://hz.zu.anjuke.com/fangyuan/1272631701"
                            >钱江国际商务中心蛋壳公寓直租 月付无压力 无 南星</a>

我们要提取其中的链接地址和标签里的文本内容

step1 编译正则

pattern := `href="(https://hz.zu.anjuke.com/fangyuan/\d+)"\s*>([^<]+)</a>``
re := regexp.MustCompile(pattern)

编译正则有两个函数分别是 regexp.MustCompileregexp.Compile ,第一个遇到错误会直接 panic ,第二个 则会返回错误信息,通常两者的使用是根据是否是输入正则(选后面)还是固定正则(选前面)

step2 提取内容

正则提取内容有很多函数,常见的有以下几个,我们根据需要选择相应的函数

//1. 字节流查找单个匹配 然后终止
re.Find(b []byte) 
//2. 字节流查找多个匹配
re.FindAll(b []byte , n int)
//3. 字节流查找多个匹配 并提取子匹配项
re.FindAllSubmatch(b []byte , n int)

//4. 字符串匹配单个
re.FindString(s string)
//5. 字符串匹配多个
re.FindAllString(s string, n int)
//6. 字符串匹配单个 并提取子匹配项
re.FindStringSubmatch(s string)
//7. 字符串匹配多个 并提取子匹配项
re.FindAllStringSubmatch((s string,n int)

这里我们选择 FindAllStringSubmatch

// 第二个参数为 -1 时 表示搜索所有匹配的子串
resName := HouseName.FindAllStringSubmatch(contents,-1)
for k,m := range resName {
	fmt.Printf("名称 : %s  link : %s \n",m[2],m[1])
}

正则匹配返回的是一个字符串切片,每个切片里包含了一个子切片,子切片中存储了对应的子匹配项,我们用 for...range 即可循环出来

打印部分结果:

手摸手教你用 <a href='https://www.codercto.com/topics/6127.html'>go</a> 写爬虫之二(准备知识:正则解析有效信息)

2. 实例

结合前一节讲的网页抓取 以及上面提到的正则,我们写了一个实例 将提取以下信息:

手摸手教你用go写爬虫之二(准备知识:正则解析有效信息)

实例代码:

var (
	/*
	`<a
                                target="_blank"
                                title="钱江国际商务中心蛋壳公寓直租 月付无压力 无 南星"
                                _soj="Filter_56&hfilter=filterlist"
                                href="https://hz.zu.anjuke.com/fangyuan/1272631701"
                            >钱江国际商务中心蛋壳公寓直租 月付无压力 无 南星</a>`*/
	HouseName = regexp.MustCompile(`href="(https://hz.zu.anjuke.com/fangyuan/\d+)"\s*>([^<]+)</a>`)
	/*
	<p class="details-item tag">
		1室1厅<span>|</span>35平米<span>|</span>12/19层<i class="iconfont jjr-icon"></i>姚礼东                        </p>
	*/
	HouseInfo = regexp.MustCompile(`<p class="details-item tag">\s+([^<]+)<span>\|</span>(\d+平米)<span>\|</span>(\d+\/\d+层)<i class="iconfont jjr-icon"></i>([^<]+)</p>`)
	HousePrice = regexp.MustCompile(`<p><strong>(\d+)</strong> 元/月</p>`)
)

func GetContents(url string) (string ,error) {

	resp,err := http.Get(url)
	if err != nil {
		return "",err
	}
	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return "", fmt.Errorf("get content failed status code is %d ",resp.StatusCode)
	}
	bytes,err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "" , nil
	}
	return string(bytes),nil
}


func main() {
	//1. 获取网页内容部分
	url := "https://hz.zu.anjuke.com/fangyuan/xiaoshan/"
	contents,err := GetContents(url)
	if err != nil {
		fmt.Println(err)
		return
	}

	//解析网页内容部分
	resName := HouseName.FindAllStringSubmatch(contents,-1)
	resInfo := HouseInfo.FindAllStringSubmatch(contents,-1)
	resPrice := HousePrice.FindAllStringSubmatch(contents,-1)

	if err != nil {
		panic(err)
		return
	}
	for k,m := range resName {
		username := strings.TrimSpace(resInfo[k][4])
		fmt.Printf("名称 : %s  信息 : %s %s %s %s 价格:%s\n",m[2],resInfo[k][1],resInfo[k][2],resInfo[k][3],username,resPrice[k][1])
	}
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

第二曲线:跨越“S型曲线”的二次增长

第二曲线:跨越“S型曲线”的二次增长

[英]查尔斯·汉迪(Charles Handy) / 苗青 / 机械工业出版社 / 2017-6 / 49.00

S型曲线是每个组织和企业在预测未来时一定会参考的工具,一切事物的发展都逃不开S型曲线(“第一曲线”)。 然而,从公司组织、企业治理、市场的变化,到个人职业发展、社会人际关系以及未来的教育与社会价值,多维度地探讨这个世界需要重新以不同的角度来思考问题,不能够总是停留在“第一曲线”的世界。 如果组织和企业能在第一曲线到达巅峰之前,找到带领企业二次腾飞的“第二曲线”,并且第二曲线必须在第一曲......一起来看看 《第二曲线:跨越“S型曲线”的二次增长》 这本书的介绍吧!

JSON 在线解析
JSON 在线解析

在线 JSON 格式化工具

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

XML、JSON 在线转换
XML、JSON 在线转换

在线XML、JSON转换工具