一、前言
1、爱汉服 去看看
2、这个小姐姐在这里哈
【汉服美景】是谁把春光剪成一树繁花?去看看
二、起因
1、看到一位博主写了一篇python爬取汉服图片的博文
2、精美汉服,送女友必备,python百行代码带你玩进汉服圈! 去看看
3、我估摸着,python已经有人写了,那我就用go来实现一下吧:思路都差不多了,就是语法有点区别
三、思路讲解
1、除了入口函数main(),有6个函数,他们的分工明确。
- main():入口函数
2、其他函数
1)、everyPage():处理每一页的数据
- for循环处理每一页的数据,获取到当前页的html(getHtmlByUrl()方法获取url的html),正则匹配每篇文章的detailUrl(文章链接)和title(文章标题)
2)、everyArticle():处理每一篇文章的数据
- 根据文章的标题:创建名为标题名的文件夹存放该篇文章的图片(createDir()方法创建文件夹)
- 根据文章的链接:获取文章的html(getHtmlByUrl()方法获取url的html)。正则匹配到该文章的的所有图片,然后把图片下载到本地(saveFile()方法)。
- 把文章的标题和文章的链接记录日志(logger()记录日志)
3)、getHtmlByUrl():根据url地址返回string类型的html字符串
- 根据url链接返回html字符串,如果异常则返回空字符串
4)、createDir():根据文件夹的名字递归创建文件夹
5)、saveFile():保存图片到本地
- 根据图片的url获取图片的内容(getHtmlByUrl()方法获取url的html
- 把string转为[]byte),存到本地。
6)、logger():存日志文件
- 记录日志,如果日志文件不存在则创建,文件的内容问追加模式(os.O_APPEND),每次调用之前的内容不会被清空。
7)、总结:获取到图片的url地址,然后下载到本地
四、代码
package main
import (
"bytes"
"fmt"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"regexp"
"strconv"
"strings"
)
//入口函数
func main() {
startPage := 1 //开始页
//endPage := 125
endPage := 3 //结束页
//入口页 http://www.aihanfu.com/zixun/tushang-1/
//结束页 http://www.aihanfu.com/zixun/tushang-125/
//不难看出,目前是总共有125页,那就来一个循环,从[1, 125]页,遍历每页的数据
// 也可以动态获取最后一页(125):根据第一页的html内容定位到最后一页的值(125)
everyPage(startPage, endPage)
}
//处理每一页的数据
func everyPage(startPage int, endPage int) {
url := "http://www.aihanfu.com/zixun/tushang-"
fmt.Println("开始处理...")
for page := startPage; page <= endPage; page++{ //循环每一页的数据
fmt.Printf("处理第 [ %d ] 页的数据\n", page)
pageUrl := url + strconv.Itoa(page) //每页pageUrl拼接 = url + page转字符串
html := getHtmlByUrl(pageUrl) //获取当前页的html内容
if html == "" { //html为空,继续下一页
continue
}
//单篇文章的html如下,我们可以写匹配语句匹配(标题,链接)了
//<h3 class="yh"><a target="_blank" href="http://www.aihanfu.com/wen/8332/">【汉服美景】天地之间,你是另一种绝色</a></h3>
pattern := "<h3 class=\"yh\"><a target=\"_blank\" href=\"(.*?)\">([^<]+)</a>" //注意原文中"_blank"是双引号就要写为双引号,不能写成单引号,要用转义字符转一下
compile := regexp.MustCompile(pattern)
result := compile.FindAllStringSubmatch(html, -1) //正则匹配,结果为 [][]string数组
if result == nil { //匹配失败,继续下一个匹配
continue
}
//循环获取每一篇文章的内容
for key, value := range result{ //循环 [][]string数组
fmt.Printf("处理第 [ %d ] 页 第 [%d] 篇文章的数据\n", page, (key+1))
detailUrl := value[1] //文章详情页链接
title := value[2] //文章标题
everyArticle(detailUrl, title) //处理每一篇文章
logger(title + " - " + detailUrl, "log.txt") //记录日志
}
}
fmt.Println("处理完成!!!")
}
//处理每一篇文章的数据
func everyArticle(url string, title string) {
html := getHtmlByUrl(url) //获取文件的详情
if html == "" {
return
}
//详情页一张图片的Html内容如下,我们可以写匹配的语句了
//<figure class="image img_wrap"><img src='http://static.aihanfu.net/uploadfile/2020/0304/20200304115441875.png' /></figure>
pattern := "<figure class=\"image img_wrap\"><img src='(.*?)' /></figure>"
compile := regexp.MustCompile(pattern)
result := compile.FindAllStringSubmatch(html, -1)
if result == nil { //匹配失败,继续下一个匹配
return
}
dir := createDir(title) //根据标题名创建文件夹
//循环获取每一张图片的内容
for _, value := range result{
imageUrl := value[1] //图片链接
//设置文件名:获取 http://static.aihanfu.net/uploadfile/2020/0520/20200520112218848.jpeg 的 20200520112218848.jpeg 作为文件名
lastEqIndex := strings.LastIndex(imageUrl, "/")
fileName := imageUrl[lastEqIndex+1:] //最后一个/后面的内容
savePath := dir + "/" + fileName //保存到本地的地址:地址 + / + 图片名
saveFile(imageUrl, savePath) //图片下载操作
}
return
}
//根据url获取html,并转为string
func getHtmlByUrl(url string) string{
html := ""
resp, err := http.Get(url)
if err == nil {
body, err := ioutil.ReadAll(resp.Body)
resp.Body.Close()
if err == nil {
html = string(body) //byte转为string
}
}
return html
}
//创建名为dirName的文件夹,用于存放该文章的图片
func createDir(dirName string) string{
dir := "./image/" + dirName //创建文件夹时,可能因为文件名含有非法字符(\ / : * ? " < > |)非法而报错
//如果文件夹不存在,则创建
_, err := os.Stat(dir)
if err != nil {
//os.Mkdir(dir, os.ModePerm) //创建单个文件夹
os.MkdirAll(dir, os.ModePerm) //递归创建文件夹
}
return dir
}
//保存文件操作
func saveFile(pictureUrl string, savePath string){
//判断文件是否存在,如果存在,说明已经下载了,直接return,下载下一张图片
_, err := os.Stat(savePath)
if err == nil {
fmt.Printf("图片已下载 [ %s ] - [ %s ]\n", pictureUrl, savePath)
return
}
html := getHtmlByUrl(pictureUrl)
if html == ""{
fmt.Printf("图片获取失败 [ %s ] - [ %s ] \n", pictureUrl, savePath)
return
}
out, _ := os.Create(savePath)
io.Copy(out, bytes.NewReader([]byte(html))) //string 转为[]byte
//循环结束,我们认为图片已经下载成功,控制台输出提示
fmt.Printf("图片 [ %s ] 下载 [ %s ] 成功\n", pictureUrl, savePath)
}
//写日志
func logger(content string, logFile string){
//判断文件是否存在,不存在则创建
_, err := os.Stat(logFile)
if err != nil {
os.Create(logFile)
}
//设置文件类型为追加
file, err := os.OpenFile(logFile, os.O_APPEND|os.O_CREATE, 666)
if err != nil {
log.Fatalln("fail to open log file")
return
}
logger := log.New(file, "", log.LstdFlags) //设置日志的记录格式
logger.Println(content) //记录(写入)日志
}
五、控制台输出
六、日志
2020/05/22 17:42:33 【汉服少年】风起山峦,男儿有志在四方 - http://www.aihanfu.com/wen/8480/
2020/05/22 17:42:33 【汉服仕女】我见过青山如黛,却远不及你眉眼半分 - http://www.aihanfu.com/wen/8475/
2020/05/22 17:42:33 【汉服美景】云中开宝刹,碧海信浮槎 - http://www.aihanfu.com/wen/8471/
2020/05/22 17:42:33 【汉服摄影】一瞥便是惊鸿,芳华乱了浮生 - http://www.aihanfu.com/wen/8467/
2020/05/22 17:42:34 【汉服美景】掬水月在手,弄花香满衣 - http://www.aihanfu.com/wen/8465/
2020/05/22 17:42:34 【汉服摄影】少即是多,简单而美 - http://www.aihanfu.com/wen/8464/
2020/05/22 17:42:34 【汉服摄影】月洞门里走出一对小仙女 - http://www.aihanfu.com/wen/8462/
2020/05/22 17:42:34 【汉服夜景】春光浪属夜樱花 - http://www.aihanfu.com/wen/8459/
2020/05/22 17:42:34 【汉服私影】红豆生南国 - http://www.aihanfu.com/wen/8456/
2020/05/22 17:42:34 【汉服少年】花间少年美如画,行也思君,坐也思君 - http://www.aihanfu.com/wen/8454/
2020/05/22 17:42:35 【汉服摄影】湖海是你,日月星辰亦是你 - http://www.aihanfu.com/wen/8453/
2020/05/22 17:42:35 【汉服摄影】佛光 菩提并无树,明镜亦无台 - http://www.aihanfu.com/wen/8452/
2020/05/22 17:42:35 【汉服摄影】颐和园 遇见古典之美 - http://www.aihanfu.com/wen/8451/
2020/05/22 17:42:35 【汉服摄影】千千素雪 不及 眉间一点红 - http://www.aihanfu.com/wen/8449/
2020/05/22 17:42:35 【汉服摄影】敦煌美学,现代女子图鉴 - http://www.aihanfu.com/wen/8446/
2020/05/22 17:42:35 【汉服摄影】大明少女与苏州园林才是绝配 - http://www.aihanfu.com/wen/8445/
2020/05/22 17:42:36 【汉服美景】梦里有一场樱雨,醒来去哪里找这样的仙境? - http://www.aihanfu.com/wen/8438/
2020/05/22 17:42:36 【汉服摄影】森林里一抹蓝色忧郁 - http://www.aihanfu.com/wen/8435/
2020/05/22 17:42:36 【汉服摄影】旋转,舞动的最美的时刻 - http://www.aihanfu.com/wen/8434/
2020/05/22 17:42:36 【汉服CP】四九青梅酸甜微醺!是心动的感觉~ - http://www.aihanfu.com/wen/8430/
2020/05/22 17:42:36 【汉服美景】微笑向暖,喜欢在春天里流连 - http://www.aihanfu.com/wen/8414/
2020/05/22 17:42:37 【汉服摄影】诗经·国风·郑风·野有蔓草 - http://www.aihanfu.com/wen/8408/
2020/05/22 17:42:37 【汉服摄影】尘事如潮人如水,只叹江湖几人回。 - http://www.aihanfu.com/wen/8407/
2020/05/22 17:42:37 【汉服美景】江南无所有,聊赠一枝春 - http://www.aihanfu.com/wen/8404/
2020/05/22 17:42:37 【汉服美景】是谁把春光剪成一树繁花? - http://www.aihanfu.com/wen/8397/
2020/05/22 17:42:37 【汉服仕女】可叹停机德,金簪雪里埋 - http://www.aihanfu.com/wen/8396/
2020/05/22 17:42:37 【汉服美景】你和三月,都是春天 - http://www.aihanfu.com/wen/8391/
2020/05/22 17:42:37 【汉服仕女】张都尉,你的檀棋请查收~ - http://www.aihanfu.com/wen/8387/
2020/05/22 17:42:37 【汉服摄影】聊斋志异 · 婴宁 - http://www.aihanfu.com/wen/8383/
2020/05/22 17:42:38 【汉服少年】陌上谁家年少足风流?启祯兄弟的日常 - http://www.aihanfu.com/wen/8382/