昨天我们一起爬取珍爱网首页,拿到了城市列表页面,接下来在返回体城市列表中提取城市和url,即下图中的a标签里的href的值和innerText值。

提取a标签,可以通过CSS选择器来选择,如下:

$('#cityList>dd>a');就可以获取到470个a标签:

这里只提供一个思路,go语言标准库里没有CSS解析库,通过第三方库可以实现。具体可以参考文章:

https://my.oschina.net/2xixi/blog/488811

http://liyangliang.me/posts/2016/03/zhihu-go-insight-parsing-html-with-goquery/

这两篇文章都是用goquery解析 HTML,用到了库:

https://github.com/PuerkitoBio/goquery

也可以用xpath去解析html,可以参考:

https://github.com/antchfx/xquery

xpath和goquery相比还是比较麻烦的,通过以下这张图可以看出来goquery要活跃的多:

我们这里不用xpath,也不用goquery提取,用更加通用的正则表达式来提取。

从上图可以看出,返回体中的a标签里都是这种形式,XXX表示城市拼音,XX表示城市中文,其他的都一样。

  1. <a href="http://www.zhenai.com/zhenghun/XXX"
  2. class="">XX</a>

所以可以写出以下的正则表达式来匹配:

  1. compile := regexp.MustCompile(`<a href="http://www.zhenai.com/zhenghun/[0-9a-z]+"[^>]*>[^<]+</a>`)

正则表达式说明:

  1. 1href的值都类似http://www.zhenai.com/zhenghun/XX
  2. 2XX可以是数字和小写字母,所以[0-9a-z],+表示至少有一个
  3. 3、[^>]*表示匹配不是>的其他字符任意次
  4. 4、[^<]+表示匹配不是<的其他字符至少一次

然后利用分组获取url和城市,代码如下:

  1. func printAllCityInfo(body []byte){
  2. //href的值都类似http://www.zhenai.com/zhenghun/XX
  3. //XX可以是数字和小写字母,所以[0-9a-z],+表示至少有一个
  4. //[^>]*表示匹配不是>的其他字符任意次
  5. //[^<]+表示匹配不是<的其他字符至少一次
  6. compile := regexp.MustCompile(`<a href="(http://www.zhenai.com/zhenghun/[0-9a-z]+)"[^>]*>([^<]+)</a>`)
  7. submatch := compile.FindAllSubmatch(body, -1)
  8. for _, matches := range submatch {
  9. //打印
  10. fmt.Printf("City:%s URL:%s\n", matches[2], matches[1])
  11. }
  12. //可以看到匹配个数为470个
  13. fmt.Printf("Matches count: %d\n", len(submatch))
  14. }

那么提取URL和City的完整代码如下:

  1. package main
  2. import (
  3. "fmt"
  4. "io/ioutil"
  5. "net/http"
  6. "golang.org/x/text/transform"
  7. //"golang.org/x/text/encoding/simplifiedchinese"
  8. "io"
  9. "golang.org/x/text/encoding"
  10. "bufio"
  11. "golang.org/x/net/html/charset"
  12. "regexp"
  13. )
  14. func main() {
  15. //返送请求获取返回结果
  16. resp, err := http.Get("http://www.zhenai.com/zhenghun")
  17. if err != nil {
  18. panic(fmt.Errorf("Error: http Get, err is %v\n", err))
  19. }
  20. //关闭response body
  21. defer resp.Body.Close()
  22. if resp.StatusCode != http.StatusOK {
  23. fmt.Println("Error: statuscode is ", resp.StatusCode)
  24. return
  25. }
  26. //utf8Reader := transform.NewReader(resp.Body, simplifiedchinese.GBK.NewDecoder())
  27. utf8Reader := transform.NewReader(resp.Body, determinEncoding(resp.Body).NewDecoder())
  28. body, err := ioutil.ReadAll(utf8Reader)
  29. if err != nil {
  30. fmt.Println("Error read body, error is ", err)
  31. }
  32. printAllCityInfo(body)
  33. //打印返回值
  34. //fmt.Println("body is ", string(body))
  35. }
  36. func determinEncoding(r io.Reader) encoding.Encoding {
  37. //这里的r读取完得保证resp.Body还可读
  38. body, err := bufio.NewReader(r).Peek(1024)
  39. if err != nil {
  40. fmt.Println("Error: peek 1024 byte of body err is ", err)
  41. }
  42. //这里简化,不取是否确认
  43. e, _, _ := charset.DetermineEncoding(body, "")
  44. return e
  45. }
  46. func printAllCityInfo(body []byte){
  47. //href的值都类似http://www.zhenai.com/zhenghun/XX
  48. //XX可以是数字和小写字母,所以[0-9a-z],+表示至少有一个
  49. //[^>]*表示匹配不是>的其他字符任意次
  50. //[^<]+表示匹配不是<的其他字符至少一次
  51. compile := regexp.MustCompile(`<a href="(http://www.zhenai.com/zhenghun/[0-9a-z]+)"[^>]*>([^<]+)</a>`)
  52. /*matches := compile.FindAll(body, -1)
  53. //matches是二维数组[][]byte
  54. for _, m := range matches {
  55. fmt.Printf("%s\n", m)
  56. }
  57. */
  58. submatch := compile.FindAllSubmatch(body, -1)
  59. //submatch是三维数组[][][]byte
  60. /* for _, matches := range submatch {
  61. //[][]byte
  62. for _, m := range matches {
  63. fmt.Printf("%s ", m)
  64. }
  65. fmt.Println()
  66. }*/
  67. for _, matches := range submatch {
  68. //打印
  69. fmt.Printf("City:%s URL:%s\n", matches[2], matches[1])
  70. }
  71. //可以看到匹配个数为470个
  72. fmt.Printf("Matches count: %d\n", len(submatch))
  73. //打印abc
  74. //fmt.Printf("%s\n", []byte{97,98,99})
  75. }

运行后,可以看到输出了URL和City:

今天我们完成了URL和城市的提取,明天我们将利用URL,来进一步分析城市的男女性个人信息。



本公众号免费提供csdn下载服务,海量IT学习资源,如果你准备入IT坑,励志成为优秀的程序猿,那么这些资源很适合你,包括但不限于java、go、python、springcloud、elk、嵌入式 、大数据、面试资料、前端 等资源。同时我们组建了一个技术交流群,里面有很多大佬,会不定时分享技术文章,如果你想来一起学习提高,可以公众号后台回复【2】,免费邀请加技术交流群互相学习提高,会不定期分享编程IT相关资源。


扫码关注,精彩内容第一时间推给你

用go语言爬取珍爱网 | 第二回的更多相关文章

  1. 用go语言爬取珍爱网 | 第一回

    我们来用go语言爬取"珍爱网"用户信息. 首先分析到请求url为: http://www.zhenai.com/zhenghun 接下来用go请求该url,代码如下: packag ...

  2. 用go语言爬取珍爱网 | 第三回

    前两节我们获取到了城市的URL和城市名,今天我们来解析用户信息. 用go语言爬取珍爱网 | 第一回 用go语言爬取珍爱网 | 第二回 爬虫的算法: 我们要提取返回体中的城市列表,需要用到城市列表解析器 ...

  3. Python爬虫之爬取慕课网课程评分

    BS是什么? BeautifulSoup是一个基于标签的文本解析工具.可以根据标签提取想要的内容,很适合处理html和xml这类语言文本.如果你希望了解更多关于BS的介绍和用法,请看Beautiful ...

  4. GoLang爬取花瓣网美女图片

    由于之前一直想爬取花瓣网(http://huaban.com/partner/uc/aimeinv/pins/) 的图片,又迫于没时间,所以拖了很久. 鉴于最近在学go语言,就刚好用这个练手了. 预览 ...

  5. 网络爬虫之定向爬虫:爬取当当网2015年图书销售排行榜信息(Crawler)

    做了个爬虫,爬取当当网--2015年图书销售排行榜 TOP500 爬取的基本思想是:通过浏览网页,列出你所想要获取的信息,然后通过浏览网页的源码和检查(这里用的是chrome)来获相关信息的节点,最后 ...

  6. 使用python爬取东方财富网机构调研数据

    最近有一个需求,需要爬取东方财富网的机构调研数据.数据所在的网页地址为: 机构调研 网页如下所示: 可见数据共有8464页,此处不能直接使用scrapy爬虫进行爬取,因为点击下一页时,浏览器只是发起了 ...

  7. Node.js爬虫-爬取慕课网课程信息

    第一次学习Node.js爬虫,所以这时一个简单的爬虫,Node.js的好处就是可以并发的执行 这个爬虫主要就是获取慕课网的课程信息,并把获得的信息存储到一个文件中,其中要用到cheerio库,它可以让 ...

  8. python 爬虫之爬取大街网(思路)

    由于需要,本人需要对大街网招聘信息进行分析,故写了个爬虫进行爬取.这里我将记录一下,本人爬取大街网的思路. 附:爬取得数据仅供自己分析所用,并未用作其它用途. 附:本篇适合有一定 爬虫基础 crawl ...

  9. 基于爬取百合网的数据,用matplotlib生成图表

    爬取百合网的数据链接:http://www.cnblogs.com/YuWeiXiF/p/8439552.html 总共爬了22779条数据.第一次接触matplotlib库,以下代码参考了matpl ...

随机推荐

  1. 【LeetCode】DFS 总结

    DFS(深度优先搜索) 常用来解决可达性的问题. 两个要点: 栈:用栈来保存当前节点信息,当遍历新节点返回时能够继续遍历当前节点.可以使用递归栈. 标记:和 BFS 一样同样需要对已经遍历过的节点进行 ...

  2. Linux-配置YUM仓库

    范例:配置Yum仓库 Yum软件仓库的作用是为了进一步简化RPM管理软件的难度以及自动分析所需软件包及其依赖关系的技术.可以把Yum想象成是一个硕大的软件仓库,里面保存有几乎所有常用的工具,而且只需要 ...

  3. 解锁HMC8及HMC9的root用户

    某天需要用HMC的root用户干点“坏事”,发现找了一圈都没有正确的HMC v8及v9的root用户破解教程,然后自己研究了一下,发现可以用root用户了.本文测试用的HMC以VMware works ...

  4. 在VMware中就显示lo回环IP:127.0.0.1的解决办法。

    在VMware时由于某些原因导致,在使用ifconfig只会显示lo,不显示其他的东西 步骤:1.sudo lshw -numeric -class network 2.sudo route -nv ...

  5. .Net基础篇_学习笔记_第五天_流程控制while循环002

    using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.T ...

  6. STL中区间最值max_element和min_element的用法

    前面的博客已经讲解了nth_element寻找区间第K大的用法,现在我们来说说这两个找区间最值的用法.两个函数都包含在algorithm库中. 一.函数原型 max_element template& ...

  7. u盘重装ubuntu16.04过程遇到的问题

    该博文主要记录ubuntu16.04重装过程中分区问题 1. /swap交换区,Logical(逻辑分区),swap area; 一般为物理内存的2倍; 例如你电脑的运行内存是4G, 则/swap可以 ...

  8. 使用python发邮件(qq邮箱)

    今天打算用QQ邮箱作为示例使用的邮箱,其他邮箱基本操作一样. 第一步:首先获取QQ邮箱授权码 1.进入QQ邮箱首页,点击设置,如图, 2.然后点击账户 3.拉到这个地方,开启POP3/SMTP服务服务 ...

  9. mongodb 获取自增数

    mongodb db.getCollection('user').findAndModify({update:{$inc:{'level':1}},query:{"name":&q ...

  10. oracle异机恢复测试

    (一)问题背景 最近在生产环境中,开发人员误操作,使用truncate将oracle数据库某个表的数据全部删除了,在删除之后,开发人员发现自己闯祸了,于是联系值班的DBA进行紧急数据恢复. 经过分析, ...