Golang - 爬虫案例实践

1. 爬虫步骤

  1. 明确目标(确定在哪个网址搜索)
  2. 爬(爬下数据)
  3. 取(去掉没用的数据)
  4. 处理数据(按具体业务去使用数据)

2. 正则表达式

  • 文档:https://studygolang.com/pkgdoc

  • API

  • re := regexp.MustCompile(reStr):传入正则表达式,得到正则表达式对象

  • ret := re.FindAllStringSubmatch(srcStr,-1):用正则对象提取页面中内容,srcStr是页面内容,-1代表取所有

  • 爬邮箱

  • 爬超链接

  • 爬手机号

  • http://www.zhaohaowang.com/

  • 爬身份证号

  • http://henan.qq.com/a/20171107/069413.htm

  • 爬图片链接

      package main
    
      import (
    "net/http"
    "fmt"
    "io/ioutil"
    "regexp"
    ) var (
    //\d代表数字
    reQQEmail = `(\d+)@qq.com`
    //匹配邮箱
    reEmail = `\w+@\w+\.\w+(\.\w+)?`
    //链接
    reLink = `href="(https?://[\s\S]+?)"`
    rePhone=`1[3456789]\d\s?\d{4}\s?\d{4}`
    //410222 1987 06 13 4038
    reIdcard=`[12345678]\d{5}((19\d{2})|(20[01]))((0[1-9]|[1[012]]))((0[1-9])|[12]\d|[3[01]])\d{3}[\dXx]`
    reImg=`"(https?://[^"]+?(\.((jpg)|(jpeg)|(png)|(gif)|(ico))))"`
    ) func main2() {
    //1.爬邮箱
    //GetEmail()
    //2.抽取爬邮箱的方法
    //GetEmail2("http://tieba.baidu.com/p/2544042204")
    //3.爬超链接
    //GetLink("http://www.baidu.com/s?wd=岛国%20留下邮箱")
    //4.爬手机号
    //GetPhone("http://www.zhaohaowang.com/")
    //5.爬身份证
    //GetIdcard("http://henan.qq.com/a/20171107/069413.htm")
    //6.爬图片链接
    //GetImg("http://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&word=%E7%BE%8E%E5%A5%B3")
    } //爬邮箱
    func GetEmail() {
    //1.发送http请求,获取页面内容
    resp, err := http.Get("http://tieba.baidu.com/p/2544042204")
    //处理异常
    HandleError(err, "http.Get url")
    //关闭资源
    defer resp.Body.Close()
    //接收页面
    pageBytes, err := ioutil.ReadAll(resp.Body)
    HandleError(err, "ioutil.ReadAll")
    //打印页面内容
    pageStr := string(pageBytes)
    fmt.Println(pageStr) //2.捕获邮箱,先搞定qq邮箱
    //传入正则
    re := regexp.MustCompile(reQQEmail)
    results := re.FindAllStringSubmatch(pageStr, -1)
    for _, result := range results {
    //fmt.Println(result)
    fmt.Printf("email=%s qq=%s\n", result[0], result[1])
    }
    } //处理异常
    func HandleError(err error, why string) {
    if err != nil {
    fmt.Println(why, err)
    }
    } //抽取的爬邮箱的方法
    func GetEmail2(url string) {
    //爬页面所有数据
    pageStr := GetPageStr(url)
    re := regexp.MustCompile(reEmail)
    results := re.FindAllStringSubmatch(pageStr, -1)
    for _, result := range results {
    fmt.Println(result)
    }
    } //根据url获取页面内容
    func GetPageStr(url string) (pageStr string) {
    //1.发送http请求,获取页面内容
    resp, err := http.Get(url)
    //处理异常
    HandleError(err, "http.Get url")
    //关闭资源
    defer resp.Body.Close()
    //接收页面
    pageBytes, err := ioutil.ReadAll(resp.Body)
    HandleError(err, "ioutil.ReadAll")
    //打印页面内容
    pageStr = string(pageBytes)
    return pageStr
    } func GetLink(url string) {
    pageStr := GetPageStr(url)
    fmt.Println(pageStr)
    re := regexp.MustCompile(reLink)
    results := re.FindAllStringSubmatch(pageStr, -1)
    fmt.Printf("找到%d条结果:\n",len(results))
    for _, result := range results {
    //fmt.Println(result)
    fmt.Println(result[1])
    }
    } func GetPhone(url string) {
    pageStr := GetPageStr(url)
    fmt.Println(pageStr)
    re := regexp.MustCompile(rePhone)
    results := re.FindAllStringSubmatch(pageStr, -1)
    fmt.Printf("找到%d条结果:\n",len(results))
    for _, result := range results {
    //fmt.Println(result)
    fmt.Println(result)
    }
    } func GetIdcard(url string) {
    pageStr := GetPageStr(url)
    fmt.Println(pageStr)
    re := regexp.MustCompile(reIdcard)
    results := re.FindAllStringSubmatch(pageStr, -1)
    fmt.Printf("找到%d条结果:\n",len(results))
    for _, result := range results {
    //fmt.Println(result)
    fmt.Println(result)
    }
    } func GetImg(url string) {
    pageStr := GetPageStr(url)
    fmt.Println(pageStr)
    re := regexp.MustCompile(reImg)
    results := re.FindAllStringSubmatch(pageStr, -1)
    fmt.Printf("找到%d条结果:\n",len(results))
    for _, result := range results {
    //fmt.Println(result)
    fmt.Println(result[0])
    }
    }

3. 并发爬取美图

  • http://www.umei.cc/bizhitupian/meinvbizhi/1.htm

  • 基本分析:

  • 先测试获取页面所有内容

  • 完成图片下载

  • 并发爬虫分析:

  • 初始化数据通道(2个)

  • 爬虫协程:65个协程向管道中添加图片链接

  • 任务统计协程:检查65个任务是否都完成,完成就关闭通道

  • 下载协程:从管道中读取链接并下载

      package main
    
      import (
    "fmt"
    "net/http"
    "io/ioutil"
    "sync"
    "strconv"
    "regexp"
    "strings"
    "time"
    ) //测试是否能拿到数据
    func myTest() {
    //1.获取页面内容
    pageStr := GetPageStr("http://www.umei.cc/bizhitupian/meinvbizhi/1.htm")
    fmt.Println(pageStr)
    //2.获取图片链接
    GetImg("http://www.umei.cc/bizhitupian/meinvbizhi/1.htm")
    } //图片下载
    func TestDownloadImg() {
    ok := DownloadFile("http://i1.whymtj.com/uploads/tu/201903/9999/rne35bbd2303.jpg", "1.jpg")
    if ok {
    fmt.Println("下载成功")
    } else {
    fmt.Println("下载失败")
    }
    } //下载
    func DownloadFile(url string, filename string) (ok bool) {
    //发请求
    resp, err := http.Get(url)
    if err != nil {
    HandleError(err, "http.Get")
    return
    }
    //关闭资源
    defer resp.Body.Close()
    //读取响应内容
    fBytes, e := ioutil.ReadAll(resp.Body)
    HandleError(e, "ioutil resp.Body")
    //拼接
    filename = "D:/go_work/src/goapp01/07/img/" + filename
    //写入硬盘
    err = ioutil.WriteFile(filename, fBytes, 644)
    HandleError(err, "http.GetWrite")
    if err != nil {
    return false
    } else {
    return true
    }
    } var (
    //存图片链接的数据通道,string
    chanImageUrls chan string
    //监控通道
    chanTask chan string
    waitGroup sync.WaitGroup
    ) func main() {
    //myTest()
    //TestDownloadImg() //1.初始化数据通道
    chanImageUrls = make(chan string, 1000000)
    chanTask = make(chan string, 65) //2.爬虫协程
    for i := 1; i < 66; i++ {
    waitGroup.Add(1)
    //获取某个页面所有图片链接
    //strconv.Itoa(i):将整数转为字符串
    go getImgUrls("http://www.umei.cc/bizhitupian/weimeibizhi/" + strconv.Itoa(i) + ".htm")
    } //3.任务统计协程
    waitGroup.Add(1)
    go CheckOk() //4.下载协程
    //少开几个下载协程,开5个
    for i := 0; i < 5; i++ {
    waitGroup.Add(1)
    //下载
    go DownloadImg()
    }
    waitGroup.Wait()
    } //爬当前页所有图片链接,并添加到管道
    func getImgUrls(url string) {
    //爬当前页所有图片链接
    urls := getImgs(url)
    //添加到管道
    for _, url := range urls {
    chanImageUrls <- url
    }
    //标志当前协程任务完成
    chanTask <- url
    waitGroup.Done()
    } //拿图片链接
    func getImgs(url string) (urls []string) {
    //根据url取内容
    pageStr := GetPageStr(url)
    //获取正则对象
    re := regexp.MustCompile(reImg)
    results := re.FindAllStringSubmatch(pageStr, -1)
    fmt.Printf("找到%d条结果:\n", len(results))
    for _, result := range results {
    //fmt.Println(result)
    //fmt.Println(result)
    url := result[1]
    urls = append(urls, url)
    }
    return
    } //监控65个任务是否完成,完成则关闭通道
    func CheckOk() {
    //计数
    var count int
    for {
    url := <-chanTask
    fmt.Printf("%s 完成爬取任务\n", url)
    count++
    if count == 65 {
    close(chanImageUrls)
    break
    }
    }
    waitGroup.Done()
    } //下载图片
    func DownloadImg() {
    for url := range chanImageUrls {
    //得到全路径
    filename := GetFilenameFromUrl(url, "D:/go_work/src/goapp01/07/img/")
    //保存到硬盘
    ok := DownloadFile(url, filename)
    if ok {
    fmt.Printf("%s 下载成功\n", filename)
    } else {
    fmt.Printf("%s 下载失败\n", filename)
    }
    }
    } //拼接文件名
    func GetFilenameFromUrl(url string, dirPath string) (filename string) {
    //strings包的方法,截取最后一个/
    lastIndex := strings.LastIndex(url, "/")
    filename = url[lastIndex+1:]
    //加一个时间戳,防止重名
    timePrefix := strconv.Itoa(int(time.Now().UnixNano()))
    filename = timePrefix + "_" + filename
    filename = dirPath + filename
    return
    }

Golang - 爬虫案例实践的更多相关文章

  1. Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳实践

    目录 [TOC] 1.RabbitMQ介绍 1.1.什么是RabbitMQ?   RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol ...

  2. Golang爬虫示例包系列教程(一):pedaily.com投资界爬虫

    Golang爬虫示例包 文件结构 自己用Golang原生包封装了一个爬虫库,源码见go get -u -v github.com/hunterhug/go_tool/spider ---- data ...

  3. CSS典型案例实践

    CSS案例实践 一.层布局:定位元素重叠 在CSS中可以通过z-index属性来确定定位元素的层叠等级.需要注意的是: z-index属性只有在元素的position属性取值为relative.abs ...

  4. Selenium自动化测试项目案例实践公开课

    Selenium自动化测试项目案例实践公开课: http://gdtesting.cn/news.php?id=55

  5. TOP100summit 2017:小米唐沐等大咖精心挑选的100个年度研发案例实践

    2017年,机器学习.大数据.人工智能等词汇成为软件研发行业的主流,大前端.DevOps.区块链等技术方式成为热点方向:2017年,智能硬件开始成为新的焦点,这一年更被称为智能音箱井喷的一年:2017 ...

  6. 爬虫beautifulsoup实践

    爬虫beautifulsoup实践: 目的:在https://unsplash.com/上爬取图片并保存到本地文件夹里.   一.观察response.首先,在Chrome浏览器里观察一下该网页的re ...

  7. ASP.NET Core基于K8S的微服务电商案例实践--学习笔记

    摘要 一个完整的电商项目微服务的实践过程,从选型.业务设计.架构设计到开发过程管理.以及上线运维的完整过程总结与剖析. 讲师介绍 产品需求介绍 纯线上商城 线上线下一体化 跨行业 跨商业模式 从0开始 ...

  8. Python 简单爬虫案例

    Python 简单爬虫案例 import requests url = "https://www.sogou.com/web" # 封装参数 wd = input('enter a ...

  9. STM32单片机应用与全案例实践 /stm32自学笔记 第二版 pdf

    STM32单片机应用与全案例实践pdf https://pan.baidu.com/s/16WrivuLcHvLTwS__Zcwl6Q 4rj3 stm32自学笔记 第二版 pdf https://p ...

随机推荐

  1. MySQL基础教程-绝对推荐

    https://wenku.baidu.com/view/1acfe579ee06eff9aef80752.html?from=search MySQL--公司培训PPT Mysql体系结构以及与Or ...

  2. Android+Jquery Mobile学习系列(3)-创建Android项目

    前两章分别对开发环境和Jquery Mobile基础知识进行了介绍,本章介绍创建一个Android项目,并使用WebView控件显示HTML数据. 首先创建一个Android Application项 ...

  3. hdoj--3790--最短路径问题(双权值迪杰斯特拉)

     最短路径问题 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total ...

  4. 洛谷P3808 & P3796 AC自动机模板

    题目:P3808:https://www.luogu.org/problemnew/show/P3808 P3796:https://www.luogu.org/problemnew/show/P37 ...

  5. SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章)

    SQL Server2012 T-SQL基础教程--读书笔记(8 - 10章) 示例数据库:点我 CHAPTER 08 数据修改 8.1 插入数据 8.1.1 INSERT VALUES 语句 8.1 ...

  6. vs2010永久删除项目的相关操作

    1.选中要删除的项目,在解决方案资源管理器中,直接左键点击一下即可.. 2.点击键盘的删除键“DElect”. 3.然后找到工程的目录后,删除项目.即可永久性删除不在需要的程序或者是项目.

  7. PCB 无需解压,直接读取Zip压缩包指定文件 实现方法

    最近有一项需求,将电测试点数后台批量写入到工程系统流程指示中,而电测试文件存在压缩包中,压缩包存在公共网络盘 示例图: 一.采用原始方法(4步完成): 第1步:.网络盘ZIP拷到本地, 第2步:解压Z ...

  8. Spell checker(串)

    http://poj.org/problem?id=1035 题意:给定一个单词判断其是否在字典中,若存在输出"%s is correct",否则判断该单词删掉一个字母,或增加一个 ...

  9. 跳出双重for循环的案例__________跳出当前循环(continue out)

    package com.etc.operator; public class demo { public static void main(String[] args) { // break out; ...

  10. Burn Down Chart(2018.5.28~2018.6.3)

    任务安排 (2018.6.2 更新——前端总进度) (2018.6.3 更新——后端燃尽图) 娄雨禛[前端部分] 曾子轩[后端部分+燃尽图] 前端 齐天扬+刘鼎乾:设计两组页面,只要求框架和简单的 c ...