本帖最后由 18978429109 于 2022-3-20 01:05 编辑
效果图
-----------------------------------------------------------------------------------------------------------------------------------------------------------------
上代码
[Golang] 纯文本查看 复制代码 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
}
|