Golang - 爬虫案例实践

目录

  • Golang - 爬虫案例实践

    • 1. 爬虫步骤
    • 2. 正则表达式
    • 3. 并发爬取美图

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 = `\[email protected]\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
      }

原文地址:https://www.cnblogs.com/konghui/p/10742153.html

时间: 2024-10-10 19:35:42

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

CSS典型案例实践

CSS案例实践 一.层布局:定位元素重叠 在CSS中可以通过z-index属性来确定定位元素的层叠等级.需要注意的是: z-index属性只有在元素的position属性取值为relative.absolute或fixed时才可以使用. 在z-index属性中,其值越大层叠级别就越高,如果两个绝对定位的元素的该属性具有相同的number值,那么将依据它们在HTML文档中声明的顺序层叠. z-index属性只能在同一级别的HTML上体现作用 对于未指定此属性的绝对定位元素,可以看做值为auto,即

爬虫案例

爬虫案例 爬取汽车之家,指定页面的图片url 1.爬取汽车之家,指定页面的图片url import requests from bs4 import BeautifulSoup # 获取页面数据 r1 = requests.get( url='https://www.autohome.com.cn/news/201801/912472.html#pvareaid=102624', headers={ 'Host':'www.autohome.com.cn', 'Referer':"https:/

爬虫案例—中基协数据爬取

因为工作原因,需要爬取相关网站的数据,包括中基协网站和天眼查部分数据. 一.中基协网站 爬取思路: 1.查看目标页:http://gs.amac.org.cn/amac-infodisc/api/pof/manager?rand=0.9775162173180119&page=%s&size=50 发现有随机数字串(刷新反爬措施),以及页码和每页信息条数,可以用来拼接爬取url 用一个循环爬取所有展示页面,用到requests库以及random函数生成随机数 返回的是json数据,直接用r

URL编码与解码(使用 Python3 urllib.parse) 与 贴吧小爬虫案例

一.parse.urlencode() 与parse.unquote() urllib 和urllib.request都是接受URL请求的相关模块,但是提供了不同的功能.两个最显著的不同如下: 1.urllib 仅可以接受URL,不能创建 设置了headers 的Request 类实例: 2.但是 urllib 提供 urlencode 方法用来GET查询字符串的产生,而urllib.request 则没有.(这是 urllib 和urllib.request 经常一起使用的主要原因) 3.编码

Python 简单爬虫案例

Python 简单爬虫案例 import requests url = "https://www.sogou.com/web" # 封装参数 wd = input('enter a word') param = { 'query':wd } response = requests.get(url=url,params=param) page_text = response.content fileName = wd+'.html' with open(fileName,'wb') as

第5课-中国天气网爬虫案例

一.中国天气网爬虫案例 #中国天气网爬虫 import requests from pyecharts.charts import Bar from bs4 import BeautifulSoup import copy import html5lib datas = [] data = { "city":None, "day":None, "higher_temp":None, "lower_temp":None } HE

纯golang爬虫实战(二)

接上一篇文章https://www.cnblogs.com/pu369/p/12202845.html只讲了原理,抽时间写个了实用版,将员工信息爬取到一个TXT文档中,以便于查询,上代码: //纯golang爬虫 package main import ( "bytes" "fmt" "io/ioutil" "net/http" "net/http/cookiejar" "regexp"

scrapy爬虫案例

一个简单的爬虫案例 from scrapy_redis.spiders import RedisSpider import os,urllib.request,time class XiaohuaSpider(scrapy.Spider): name = 'xiaohua' allowed_domains = ['90xiaohua.com'] start_urls = ['http://90xiaohua.com//'] file_path = r'D:\python_code\spider\

大话爬虫的实践技巧

图1-意淫爬虫与反爬虫间的对决 数据的重要性 如今已然是大数据时代,数据正在驱动着业务开发,驱动着运营手段,有了数据的支撑可以对用户进行用户画像,个性化定制,数据可以指明方案设计和决策优化方向,所以互联网产品的开发都是离不开对数据的收集和分析,数据收集的一种是方式是通过上报API进行自身平台用户交互情况的捕获,还有一种手段是通过开发爬虫程序,爬取竞品平台的数据,后面就重点说下爬虫的应用场景和实践中会遇到的问题和反反爬虫的一些套路与技巧. 应用场景 互联网平台,偏向销售公司,客户信息的爬取 客户信