golang爬虫小案例

lu569368 · · 2868 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
### 爬虫步骤 + 想要学习更多的小项目欢迎访问我的博客www.5lmh.com + 明确目标(确定在哪个网站搜索) + 爬(爬下内容) + 取(筛选想要的) + 处理数据(按照你的想法去处理) ```go package main import ( "fmt" "io/ioutil" "net/http" "regexp" ) //这个只是一个简单的版本只是获取QQ邮箱并且没有进行封装操作,另外爬出来的数据也没有进行去重操作 var ( // \d是数字 reQQEmail = `(\d+)@qq.com` ) // 爬邮箱 func GetEmail() { // 1.去网站拿数据 resp, err := http.Get("https://tieba.baidu.com/p/6051076813?red_tag=1573533731") HandleError(err, "http.Get url") defer resp.Body.Close() // 2.读取页面内容 pageBytes, err := ioutil.ReadAll(resp.Body) HandleError(err, "ioutil.ReadAll") // 字节转字符串 pageStr := string(pageBytes) //fmt.Println(pageStr) // 3.过滤数据,过滤qq邮箱 re := regexp.MustCompile(reQQEmail) // -1代表取全部 results := re.FindAllStringSubmatch(pageStr, -1) //fmt.Println(results) // 遍历结果 for _, result := range results { fmt.Println("email:", result[0]) fmt.Println("qq:", result[1]) } } // 处理异常 func HandleError(err error, why string) { if err != nil { fmt.Println(why, err) } } func main() { GetEmail() } ``` ### 正则表达式 + 文档: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 如果连接失效了自己找一个就好了 + 爬图片链接 ```go package main import ( "fmt" "io/ioutil" "net/http" "regexp" ) var ( // w代表大小写字母+数字+下划线 reEmail = `\w+@\w+\.\w+` // s?有或者没有s // +代表出1次或多次 //\s\S各种字符 // +?代表贪婪模式 reLinke = `href="(https?://[\s\S]+?)"` rePhone = `1[3456789]\d\s?\d{4}\s?\d{4}` reIdcard = `[123456789]\d{5}((19\d{2})|(20[01]\d))((0[1-9])|(1[012]))((0[1-9])|([12]\d)|(3[01]))\d{3}[\dXx]` reImg = `https?://[^"]+?(\.((jpg)|(png)|(jpeg)|(gif)|(bmp)))` ) // 处理异常 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) { resp, err := http.Get(url) HandleError(err, "http.Get url") defer resp.Body.Close() // 2.读取页面内容 pageBytes, err := ioutil.ReadAll(resp.Body) HandleError(err, "ioutil.ReadAll") // 字节转字符串 pageStr = string(pageBytes) return pageStr } func main() { // 2.抽取的爬邮箱 // GetEmail2("https://tieba.baidu.com/p/6051076813?red_tag=1573533731") // 3.爬链接 //GetLink("http://www.baidu.com/s?wd=%E8%B4%B4%E5%90%A7%20%E7%95%99%E4%B8%8B%E9%82%AE%E7%AE%B1&rsv_spt=1&rsv_iqid=0x98ace53400003985&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&tn=baiduhome_pg&rsv_enter=1&rsv_dl=ib&rsv_sug2=0&inputT=5197&rsv_sug4=6345") // 4.爬手机号 //GetPhone("https://www.zhaohaowang.com/") // 5.爬身份证号 //GetIdCard("https://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 GetIdCard(url string) { pageStr := GetPageStr(url) re := regexp.MustCompile(reIdcard) results := re.FindAllStringSubmatch(pageStr, -1) for _, result := range results { fmt.Println(result) } } // 爬链接 func GetLink(url string) { pageStr := GetPageStr(url) re := regexp.MustCompile(reLinke) results := re.FindAllStringSubmatch(pageStr, -1) for _, result := range results { fmt.Println(result[1]) } } //爬手机号 func GetPhone(url string) { pageStr := GetPageStr(url) re := regexp.MustCompile(rePhone) results := re.FindAllStringSubmatch(pageStr, -1) for _, result := range results { fmt.Println(result) } } func GetImg(url string) { pageStr := GetPageStr(url) re := regexp.MustCompile(reImg) results := re.FindAllStringSubmatch(pageStr, -1) for _, result := range results { fmt.Println(result[0]) } } ``` ### 并发爬取美图 下面的两个是即将要爬的网站,如果网址失效自己换一个就好了 + https://www.bizhizu.cn/shouji/tag-%E5%8F%AF%E7%88%B1/1.html ```go package main import ( "fmt" "io/ioutil" "net/http" "regexp" "strconv" "strings" "sync" "time" ) func HandleError(err error, why string) { if err != nil { fmt.Println(why, err) } } // 下载图片,传入的是图片叫什么 func DownloadFile(url string, filename string) (ok bool) { resp, err := http.Get(url) HandleError(err, "http.get.url") defer resp.Body.Close() bytes, err := ioutil.ReadAll(resp.Body) HandleError(err, "resp.body") filename = "E:/5lmh.com/src/github.com/student/3.0/img/" + filename // 写出数据 err = ioutil.WriteFile(filename, bytes, 0666) if err != nil { return false } else { return true } } // 并发爬思路: // 1.初始化数据管道 // 2.爬虫写出:26个协程向管道中添加图片链接 // 3.任务统计协程:检查26个任务是否都完成,完成则关闭数据管道 // 4.下载协程:从管道里读取链接并下载 var ( // 存放图片链接的数据管道 chanImageUrls chan string waitGroup sync.WaitGroup // 用于监控协程 chanTask chan string reImg = `https?://[^"]+?(\.((jpg)|(png)|(jpeg)|(gif)|(bmp)))` ) func main() { // myTest() // DownloadFile("http://i1.shaodiyejin.com/uploads/tu/201909/10242/e5794daf58_4.jpg", "1.jpg") // 1.初始化管道 chanImageUrls = make(chan string, 1000000) chanTask = make(chan string, 26) // 2.爬虫协程 for i := 1; i < 27; i++ { waitGroup.Add(1) go getImgUrls("https://www.bizhizu.cn/shouji/tag-%E5%8F%AF%E7%88%B1/" + strconv.Itoa(i) + ".html") } // 3.任务统计协程,统计26个任务是否都完成,完成则关闭管道 waitGroup.Add(1) go CheckOK() // 4.下载协程:从管道中读取链接并下载 for i := 0; i < 5; i++ { waitGroup.Add(1) go DownloadImg() } waitGroup.Wait() } // 下载图片 func DownloadImg() { for url := range chanImageUrls { filename := GetFilenameFromUrl(url) ok := DownloadFile(url, filename) if ok { fmt.Printf("%s 下载成功\n", filename) } else { fmt.Printf("%s 下载失败\n", filename) } } waitGroup.Done() } // 截取url名字 func GetFilenameFromUrl(url string) (filename string) { // 返回最后一个/的位置 lastIndex := strings.LastIndex(url, "/") // 切出来 filename = url[lastIndex+1:] // 时间戳解决重名 timePrefix := strconv.Itoa(int(time.Now().UnixNano())) filename = timePrefix + "_" + filename return } // 任务统计协程 func CheckOK() { var count int for { url := <-chanTask fmt.Printf("%s 完成了爬取任务\n", url) count++ if count == 26 { close(chanImageUrls) break } } waitGroup.Done() } // 爬图片链接到管道 // url是传的整页链接 func getImgUrls(url string) { urls := getImgs(url) // 遍历切片里所有链接,存入数据管道 for _, url := range urls { chanImageUrls <- url } // 标识当前协程完成 // 每完成一个任务,写一条数据 // 用于监控协程知道已经完成了几个任务 chanTask <- url waitGroup.Done() } // 获取当前页图片链接 func getImgs(url string) (urls []string) { pageStr := GetPageStr(url) re := regexp.MustCompile(reImg) results := re.FindAllStringSubmatch(pageStr, -1) fmt.Printf("共找到%d条结果\n", len(results)) for _, result := range results { url := result[0] urls = append(urls, url) } return } // 抽取根据url获取内容 func GetPageStr(url string) (pageStr string) { resp, err := http.Get(url) HandleError(err, "http.Get url") defer resp.Body.Close() // 2.读取页面内容 pageBytes, err := ioutil.ReadAll(resp.Body) HandleError(err, "ioutil.ReadAll") // 字节转字符串 pageStr = string(pageBytes) return pageStr } ```

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

2868 次点击  
加入收藏 微博
2 回复  |  直到
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传