Golang - 爬虫案例实践
Golang - 爬虫案例实践
1. 爬虫步骤
- 明确目标(确定在哪个网址搜索)
- 爬(爬下数据)
- 取(去掉没用的数据)
- 处理数据(按具体业务去使用数据)
2. 正则表达式
API
re := regexp.MustCompile(reStr):传入正则表达式,得到正则表达式对象
ret := re.FindAllStringSubmatch(srcStr,-1):用正则对象提取页面中内容,srcStr是页面内容,-1代表取所有
爬邮箱
爬超链接
爬手机号
爬身份证号
爬图片链接
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. 并发爬取美图
基本分析:
先测试获取页面所有内容
完成图片下载
并发爬虫分析:
初始化数据通道(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 - 爬虫案例实践的更多相关文章
- Ubuntu14.04+RabbitMQ3.6.3+Golang的最佳实践
目录 [TOC] 1.RabbitMQ介绍 1.1.什么是RabbitMQ? RabbitMQ 是由 LShift 提供的一个 Advanced Message Queuing Protocol ...
- Golang爬虫示例包系列教程(一):pedaily.com投资界爬虫
Golang爬虫示例包 文件结构 自己用Golang原生包封装了一个爬虫库,源码见go get -u -v github.com/hunterhug/go_tool/spider ---- data ...
- CSS典型案例实践
CSS案例实践 一.层布局:定位元素重叠 在CSS中可以通过z-index属性来确定定位元素的层叠等级.需要注意的是: z-index属性只有在元素的position属性取值为relative.abs ...
- Selenium自动化测试项目案例实践公开课
Selenium自动化测试项目案例实践公开课: http://gdtesting.cn/news.php?id=55
- TOP100summit 2017:小米唐沐等大咖精心挑选的100个年度研发案例实践
2017年,机器学习.大数据.人工智能等词汇成为软件研发行业的主流,大前端.DevOps.区块链等技术方式成为热点方向:2017年,智能硬件开始成为新的焦点,这一年更被称为智能音箱井喷的一年:2017 ...
- 爬虫beautifulsoup实践
爬虫beautifulsoup实践: 目的:在https://unsplash.com/上爬取图片并保存到本地文件夹里. 一.观察response.首先,在Chrome浏览器里观察一下该网页的re ...
- ASP.NET Core基于K8S的微服务电商案例实践--学习笔记
摘要 一个完整的电商项目微服务的实践过程,从选型.业务设计.架构设计到开发过程管理.以及上线运维的完整过程总结与剖析. 讲师介绍 产品需求介绍 纯线上商城 线上线下一体化 跨行业 跨商业模式 从0开始 ...
- Python 简单爬虫案例
Python 简单爬虫案例 import requests url = "https://www.sogou.com/web" # 封装参数 wd = input('enter a ...
- STM32单片机应用与全案例实践 /stm32自学笔记 第二版 pdf
STM32单片机应用与全案例实践pdf https://pan.baidu.com/s/16WrivuLcHvLTwS__Zcwl6Q 4rj3 stm32自学笔记 第二版 pdf https://p ...
随机推荐
- #定位系统性能瓶颈# sysdig
安装方法: curl -s https://s3.amazonaws.com/download.draios.com/stable/install-sysdig | sudo bash [root@l ...
- bzoj2595 [Wc2008]游览计划——斯坦纳树
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=2595 今天刚学了斯坦纳树,还不太会,写一道题练习一下: 参考了博客:http://www.c ...
- Gym - 101981G The 2018 ICPC Asia Nanjing Regional Contest G.Pyramid 找规律
题面 题意:数一个n阶三角形中,有多少个全等三角形,n<=1e9 题解:拿到题想找规律,手画开始一直数漏....,最后还是打了个表 (打表就是随便定个点为(0,0),然后(2,0),(4,0), ...
- JAVA 中进行网络通信时,通信的程序两端要传输的对象,不仅要序列化,而且这个对象所属的类的名字要完全一样,连包的名字都得一样
如上图项目目录,这是一个简易的QQ,客户端登录的时候要传输用户信息到服务器验证,所以两端都会用到User类的对象,但一开始我在Server端的包名是com.qq.server.common,两端的报名 ...
- 进击的Python【第二十二章】
day22 知识点概要 - Session - CSRF - Model操作 - Form验证(ModelForm) - 中间件 - 缓存 - 信号 内容详细: 1. Session 基于Cookie ...
- Git教程(3)git工作区与文件状态及简单示例
基础 目录: working driectory 工作目录,就是我们的工作目录,其中包括未跟踪文件及暂存区和仓库目录. staging area 暂存区,不对应一个具体目录,其实只是git di ...
- android黑科技系列——Apk混淆成中文语言代码
一.前言 最近想爆破一个app,没有加壳,简单的使用Jadx打开查看源码,结果把我逗乐了,代码中既然都是中文,而且是一些比较奇葩的中文字句,如图所示: 瞬间感觉懵逼了,这app真会玩,我们知道因为Ja ...
- android黑科技系列——应用市场省流量更新(增量升级)原理解析
一.前言 最近在看热修复相关的框架,之前我们已经看过了阿里的Dexposed和AndFix这两个框架了,不了解的同学可以点击这里进行查看:Dexposed框架原理解析 和 AndFix热修复框架原理解 ...
- Gradle sync failed: Could not find method android() for arguments 错误的解决办法
这个问题本质上是Android-gradle的一个使用限制. 对应的英文文档android_tool文档 如果你的App包含了多个Android模块, 应该尽量避免给每个模块手动指定编译SDK版本. ...
- Android ViewPager使用方法小结
android-support-v4.jar 是谷歌提供给我们的一个兼容低版本安卓设备的软件包,里面包囊了只有在 Android 3.0 以上可用的API.而 ViewPager 就是其中之一.利用它 ...