- package main
-
- import (
- "fmt"
- "io/ioutil"
- "net/http"
- "os"
- "regexp"
- "strconv"
- "strings"
- "sync"
- "time"
- )
-
- var (
- reImg = `https?://[^"]+?(.((jpg)|(png)|(jpeg)|(gif)|(bmp)))`
- taskChan chan string // 记录任务完成的通道
- imgChan chan string // 图片通道
- waitGroup sync.WaitGroup // 协程会涉及到并发,这个的作用具体的可百度
- pageStart int = 1 // 从第几页开始
- pageSize int = 30 // 扫描页数
- DownLoadPath string = "D:/HBuilderX/project/GolangProject/爬虫小案例/img/" // 此处是图片下载的地址,需要修改为你们自己的地址
- )
-
- func main() {
- fmt.Println("从第几页开始")
- fmt.Scanln(&pageStart)
-
- fmt.Println("扫描页数")
- fmt.Scanln(&pageSize)
-
- taskChan = make(chan string, pageSize) // 给管道缓冲值
- imgChan = make(chan string, 100000) // 给管道缓冲值
-
- for i := pageStart; i < pageStart+pageSize; i++ {
- waitGroup.Add(1)
- go getWebBody(i) // 获取地址的body
- }
-
- waitGroup.Add(1)
- go handleImg() // 处理img
-
- waitGroup.Add(1)
- go checkOk()
-
- waitGroup.Wait()
-
- fmt.Println("执行完毕,回车退出")
- var input string
- fmt.Scanln(&input)
- }
-
- func getWebBody(i int) {
- url := "https://www.bizhizu.cn/shouji/tag-%E5%8F%AF%E7%88%B1/" + strconv.Itoa(i) + ".html"
- resp, err := http.Get(url)
- if err != nil {
- fmt.Println(err)
- }
- defer resp.Body.Close() // 此处不可少,否则会造成内存泄露或者溢出问题
-
- body, _ := ioutil.ReadAll(resp.Body)
-
- re := regexp.MustCompile(reImg) // 正则匹配图片地址
-
- result := re.FindAllStringSubmatch(string(body), -1)
-
- println("第" + strconv.Itoa(i) + "页找到数据" + strconv.Itoa(len(result)) + "条")
-
- for _, v := range result {
- imgChan <- v[0] // 把得到的数据写到 管道 里
- }
-
- taskChan <- url
-
- waitGroup.Done()
- }
-
- // 处理图片方法
- func handleImg() {
- for url := range imgChan {
- fileName := GetFilenameFromUrl(url)
- result := DownloadFile(url, fileName)
- if result {
- fmt.Printf("已下载完毕 %v n", url)
- } else {
- fmt.Printf("下载失败 %v n", url)
- }
- }
- waitGroup.Done()
- }
-
- // 检查管道任务是否完成
- func checkOk() {
- count := 0
- for {
- url := <-taskChan
- fmt.Printf("完成爬取:%v n", url)
- count++
- if count == pageSize {
- close(imgChan)
- close(taskChan)
- break
- }
- }
-
- 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 DownloadFile(url string, filename string) bool {
- var err error
- resp, err := http.Get(url)
- if err != nil {
- fmt.Println(err)
- }
- defer resp.Body.Close()
- bytes, err := ioutil.ReadAll(resp.Body)
- if err != nil {
- fmt.Println(err)
- }
-
- if _, err := os.Stat(DownLoadPath); os.IsNotExist(err) {
- // 必须分成两步
- // 先创建文件夹
- os.Mkdir(DownLoadPath, 0777)
- // 再修改权限
- os.Chmod(DownLoadPath, 0666)
- }
-
- filename = DownLoadPath + filename
- err = ioutil.WriteFile(filename, bytes, 0666)
- if err != nil {
- return false
- }
- return true
- }
复制代码
|