> 本文介绍正则提取字符串中的相关信息
### 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"></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])
}
}
```
有疑问加站长微信联系(非本文作者))