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

wujiangwei · · 1303 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

> 本文介绍正则提取字符串中的相关信息 ### 1. 正则 > 字符串中的信息提取我们使用`regexp`包的相关函数来解决 >假设有一段html代码如下 ```html <a target="_blank" title="钱江国际商务中心蛋壳公寓直租 月付无压力 无 南星" _soj="Filter_56&hfilter=filterlist" href="https://hz.zu.anjuke.com/fangyuan/1272631701" >钱江国际商务中心蛋壳公寓直租 月付无压力 无 南星</a> ``` >我们要提取其中的链接地址和标签里的文本内容 > step1 编译正则 ```go pattern := `href="(https://hz.zu.anjuke.com/fangyuan/\d+)"\s*>([^<]+)</a>`` re := regexp.MustCompile(pattern) ``` > 编译正则有两个函数分别是 `regexp.MustCompile` 和 `regexp.Compile`,第一个遇到错误会直接`panic`,第二个 则会返回错误信息,通常两者的使用是根据是否是输入正则(选后面)还是固定正则(选前面) > step2 提取内容 > 正则提取内容有很多函数,常见的有以下几个,我们根据需要选择相应的函数 ```go //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` ```go // 第二个参数为 -1 时 表示搜索所有匹配的子串 resName := HouseName.FindAllStringSubmatch(contents,-1) for k,m := range resName { fmt.Printf("名称 : %s link : %s \n",m[2],m[1]) } ``` > 正则匹配返回的是一个字符串切片,每个切片里包含了一个子切片,子切片中存储了对应的子匹配项,我们用 `for...range`即可循环出来 >打印部分结果: <img style="width:100%;height:200" src="https://static.studygolang.com/190219/f1bdc55ab395cae38743d4ca79021a06.png"/> ### 2. 实例 > 结合前一节讲的[网页抓取](https://studygolang.com/articles/18312) 以及上面提到的正则,我们写了一个实例 将提取以下信息: <img style="width:100%;height:200" src="https://static.studygolang.com/190219/ad0f2fe2bda6cadc1bd00de6d22dca5c.png"/> >实例代码: ```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">&#xE147;</i>姚礼东 </p> */ HouseInfo = regexp.MustCompile(`<p class="details-item tag">\s+([^<]+)<span>\|</span>(\d+平米)<span>\|</span>(\d+\/\d+层)<i class="iconfont jjr-icon">&#xE147;</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]) } } ```

有疑问加站长微信联系(非本文作者))

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

1303 次点击  
加入收藏 微博
被以下专栏收入,发现更多相似内容
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传