代码还是之前的代码
package main
import (
"io/ioutil"
"log"
"net/http"
"regexp"
)
type pachong struct {
re string
url string
}
func (p *pachong) getinfo() []string { //爬虫结构体的getinfo方法
res, err := http.Get(p.url)
if err != nil {
log.Fatal(err)
}
result, err := ioutil.ReadAll(res.Body)
err = ioutil.WriteFile("abc.html", result, 0777)
//这里我输出网页源代码看看正则是否错误
res.Body.Close()
if err != nil {
log.Fatal(err)
}
re := regexp.MustCompile(p.re) //匹配正则
s := re.FindAllString(string(result), -1) //返回字符串切片,-1表示全部,1表示匹配1个,2就匹配2个
return s
}
func (p *pachong) getstring(s []string) []byte { //爬虫结构体的getstring方法
var st string
for _, v := range s {
st = st + v + "\n" //字符串拼接
}
return []byte(st)
}
func main() {
pa := &pachong{`(?U:src=["']https?://.+\.(jpg|gif|png)["'])`, "https://www.foxzc.com/"}
//这里使用非贪婪模式,试过几个网站应该是没错,但是有些网站使用了边看边加载的模式就获取不到很多图片
result := pa.getinfo()
st := pa.getstring(result) //定义一个字符串变量用来把字符串切片转换成字符串
//再把字符串转换成字节切片输入到文件
err := ioutil.WriteFile("abc.txt", st, 0777)
if err != nil {
log.Fatal(err)
}
}
下面是爬取到后下载图片
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"regexp"
)
type pachong struct {
re string//保存正则表达式
url string//保存网址
}
func (p *pachong) getinfo() []string { //爬虫结构体的getinfo方法
res, err := http.Get(p.url)
if err != nil {
log.Fatal(err)
}
result, err := ioutil.ReadAll(res.Body)
err = ioutil.WriteFile("abc.html", result, 0777)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
re := regexp.MustCompile(p.re) //匹配正则
s := re.FindAllString(string(result), -1) //返回字符串切片,-1表示全部,1表示匹配1个,2就匹配2个
return s
}
func (p *pachong) getstring(s []string) []byte { //爬虫结构体的getstring方法,把切片变成字符串拼接起来
var st string
for _, v := range s {
st = st + v + "\n" //字符串拼接
}
fmt.Println("获取到", len(s), "条信息")
return []byte(st)
}
func (p *pachong) downImg(s []string) { //传入获取到的字符串切片
for _, v := range s {
//因为获取到的样子是src="https://bbs-
//多余v[5:]取第5个字符后面的内容
st := v[5:]
res, _ := http.Get(st) //获取图片地址的对象
imgBytes, _ := ioutil.ReadAll(res.Body) //获取图片地址的字节流
res.Body.Close()
re := regexp.MustCompile(`(?U:[^/]+\.(jpg|gif|png)$)`) //这里是我写的获取文件名
imgName := re.FindString(st) //在regexp包里找到的匹配字符串输出字符串方法
path := `D:\go\img\` + imgName //img文件夹不存在的话会错误,先创建
err := ioutil.WriteFile(path, imgBytes, 0777) //保存到文件夹
if err != nil {
log.Fatal(err)
}
}
}
func main() {
pa := &pachong{`(?U:src=["']https?://.+\.(jpg|gif|png))`, "http://www.zol.com.cn/"}
result := pa.getinfo()
pa.downImg(result)
}
目前为止是同步下载的,我们简陋的修改下变成并发下载
package main
import (
"fmt"
"io/ioutil"
"log"
"net/http"
"regexp"
"sync"
)
type pachong struct {
re string
url string
}
func (p *pachong) getinfo() []string { //爬虫结构体的getinfo方法
res, err := http.Get(p.url)
if err != nil {
log.Fatal(err)
}
result, err := ioutil.ReadAll(res.Body)
err = ioutil.WriteFile("abc.html", result, 0777)
res.Body.Close()
if err != nil {
log.Fatal(err)
}
re := regexp.MustCompile(p.re) //匹配正则
s := re.FindAllString(string(result), -1) //返回字符串切片,-1表示全部,1表示匹配1个,2就匹配2个
return s
}
func (p *pachong) getstring(s []string) []byte { //爬虫结构体的getstring方法,把切片变成字符串拼接起来
var st string
for _, v := range s {
st = st + v + "\n" //字符串拼接
}
fmt.Println("获取到", len(s), "条信息")
return []byte(st)
}
func (p *pachong) downImg(s []string) { //传入获取到的字符串切片
for _, v := range s {
//因为获取到的样子是src="https://bbs-
//多余v[5:]取第5个字符后面的内容
st := v[5:]
res, _ := http.Get(st) //获取图片地址的对象
imgBytes, _ := ioutil.ReadAll(res.Body) //获取图片地址的字节流
res.Body.Close()
re := regexp.MustCompile(`(?U:[^/]+\.(jpg|gif|png)$)`) //这里是我写的获取文件名
imgName := re.FindString(st) //在regexp包里找到的匹配字符串输出字符串方法
path := `D:\go\img\` + imgName //img文件夹不存在的话会错误,先创建
err := ioutil.WriteFile(path, imgBytes, 0777) //保存到文件夹
if err != nil {
log.Fatal(err)
}
wg.Done() //程序最后执行.相当于Add(-1)
}
}
var wg sync.WaitGroup //定义WaitGroup类型
func main() {
pa := &pachong{`(?U:src=["']https?://.+\.(jpg|gif|png))`, "https://www.gamersky.com/"}
result := pa.getinfo()
wg.Add(len(result)) //添加计数器
go pa.downImg(result)
wg.Wait() //表示阻塞直到WaitGroup计数器为0
}
上面添加的计数器太多了,我们改下
var wg sync.WaitGroup //定义WaitGroup类型
func main() {
pa := &pachong{`(?U:src=["']https?://.+\.(jpg|gif|png))`, "https://www.gamersky.com/"}
result := pa.getinfo()
wg.Add(1)//添加1个计数器
go func() {//匿名函数
pa.downImg(result)
wg.Done()
}()
wg.Wait()
}
再用Channel,并发同步
var ch = make(chan int) //用channel通道
func main() {
pa := &pachong{`(?U:src=["']https?://.+\.(jpg|gif|png))`, "https://www.gamersky.com/"}
result := pa.getinfo()
go func() {
//ch <- 123,不能放在这个位置,如果放在这里接收和发送都已经完成,下面的就不一定会执行
pa.downImg(result)
ch <- 123
}()
<-ch
}