go语言goquery下载图片实例「建议收藏」

crawl.gopackagemainimport(“fmt””strings””strconv””net/http””net/url””io/ioutil””os””log””runtime””flag””github.com/PuerkitoBio/goquery”)constH

大家好,又见面了,我是你们的朋友全栈君。

crawl.go

package main
import (
"fmt"
"strings"
"strconv"
"net/http"
"net/url"
"io/ioutil"
"os"
"log"
"runtime"
"flag"
"github.com/PuerkitoBio/goquery"
)
const HOST     string  = "http://www.aitaotu.com"
const DOC_URL  string  = "http://www.aitaotu.com/search/%E9%BB%91%E4%B8%9D%E7%BE%8E%E8%85%BF/"
var (
ch1 chan string
ch2 chan string
ch3 chan int
img_dir string
)
//初始化变量
func init(){
ch1 = make(chan string, 20)
ch2 = make(chan string, 1000)
ch3 = make(chan int, 1000)
logfile, err := os.OpenFile("/var/log/crawl.log", os.O_CREATE|os.O_RDWR|os.O_APPEND, 0777)
if err != nil {
os.Exit(1)
}
log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)
log.SetOutput(logfile)
}
func main(){
runtime.GOMAXPROCS(runtime.NumCPU())
img_path := flag.String("img_path", "/data/pic/", "where is image to save")
flag.Parse()
img_dir =  *img_path
//检查目录是否存在
file, err := os.Stat(img_dir)
if err != nil || !file.IsDir() {
dir_err := os.Mkdir(img_dir, os.ModePerm)
if dir_err != nil {
fmt.Println("create dir failed")
os.Exit(1)
}
}
go getListUrl()
go parseListUrl()
go downloadImage()
count := 0
for num := range ch3 {
count = count + num
fmt.Println("count:", count)
}
fmt.Println("crawl end")
}
func getListUrl(){
doc, err := goquery.NewDocument(DOC_URL)
if err  != nil {
fmt.Println("err:", err)
os.Exit(1)
}
doc.Find(".picbox").Each(func(i int, s *goquery.Selection){
text, _    := s.Find("a").Attr("href")
list_url   := HOST + text
ch1 <- list_url
})
}
//根据模块和总数据列出所有的图片页面
func parseListUrl(){
suffix := ".html"
for list_url := range ch1 {
page_count := getPageCount(list_url)
prefix     := strings.TrimRight(list_url, suffix)
for i := 1; i <= page_count; i++ {
img_list_url := prefix + "_" + strconv.Itoa(i) + suffix
ch2 <- img_list_url
}
}
}
//获取总页数
func getPageCount(list_url string) (count int){
count = 0
doc, _ := goquery.NewDocument(list_url)
doc.Find(".pages ul li").Each(func(i int, s *goquery.Selection){
text := s.Find("a").Text()
if text == "末页" {
last_page_url, _ := s.Find("a").Attr("href")
prefix := strings.Trim(last_page_url, ".html")
index  := strings.Index(prefix, "_")
last_page_num := prefix[index+1:]
page_num, _   := strconv.Atoi(last_page_num)
count = page_num
}
})
return count
}
//解析图片url
func downloadImage(){
for img_list_url := range ch2 {
doc, _ := goquery.NewDocument(img_list_url)
doc.Find("#big-pic p a").Each(func(i int, s *goquery.Selection){
img_url, _ := s.Find("img").Attr("src")
go func(){
saveImages(img_url)
}()
})
}
}
//下载图片
func saveImages(img_url string){
log.Println(img_url)
u, err := url.Parse(img_url)
if err != nil {
log.Println("parse url failed:", img_url, err)
return 
}
//去掉最左边的'/'
tmp := strings.TrimLeft(u.Path, "/")
filename := img_dir + strings.ToLower(strings.Replace(tmp, "/", "-", -1))
exists := checkExists(filename)
if exists {
return 
}
response, err := http.Get(img_url)
if err != nil {
log.Println("get img_url failed:", err)
return 
}
defer response.Body.Close()
data, err := ioutil.ReadAll(response.Body)
if err != nil {
log.Println("read data failed:", img_url, err)
return 
}
image, err := os.Create(filename)
if err != nil {
log.Println("create file failed:", filename, err)
return 
}
ch3 <- 1
defer image.Close()
image.Write(data)
}
func checkExists(filename string) bool {
_, err := os.Stat(filename)
return err == nil 
}

cd $GOPATH/bin
编译:go build crawl
运行:./crawl –img_path=/data/pic

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

发布者:全栈程序员-用户IM,转载请注明出处:https://javaforall.cn/127443.html原文链接:https://javaforall.cn

【正版授权,激活自己账号】: Jetbrains全家桶Ide使用,1年售后保障,每天仅需1毛

【官方授权 正版激活】: 官方授权 正版激活 支持Jetbrains家族下所有IDE 使用个人JB账号...

(0)


相关推荐

  • iPhone 抓包工具Charles使用[通俗易懂]

    iPhone 抓包工具Charles使用[通俗易懂]Charles是在Mac下常用的截取网络封包的工具,在做iOS开发时,我们为了调试与服务器端的网络通讯协议,常常需要截取网络封包来分析。Charles通过将自己设置成系统的网络访问代理服务器,使得所有的网络访问请求都通过它来完成,从而实现了网络封包的截取和分析。Charles主要的功能包括:支持SSL代理。可以截取分析SSL的请求。支持流量控制。可以模拟慢速网络

  • php替换字符串中,PHP 替换字符串中的一些字符方法介绍

    php替换字符串中,PHP 替换字符串中的一些字符方法介绍在php中替换字符串我们都会使用到str_replace函数了,此函数还可以使用正则,下面小编来给大家介绍一下替换字符串中的一些字符或替换第一次出现的字符实例。现在有个需求:字符串A与字符串B,字符串B中包含字符串A,利用字符串A将字符串B中的A替换成其他字符串或删除。利用PHP函数,str_ireplace()与str_replace()可以做到。一、str_ireplace(find,r…

  • centos7下kafka集群搭建

    centos7下kafka集群搭建概述集群安装或者单机安装都可以,这里介绍集群安装。Kafka本身安装包也自带了zookeeper,也可以使用其自带的zookeeper。建议试用自己安装的zookeeper,本教程试用单独安装的zookeeper。安装环境3台centos7虚拟机:10.15.21.6210.10.182.16810.10.182.169kafka_2.10-0.10.2.0zookeeper-3.4.9

  • python与pycharm区别_pycharm与anaconda

    python与pycharm区别_pycharm与anacondaipython和pycharm的区别:pycharm是一种pythonIDE,包含使用python语言开发时提高其效率的工具;ipython是一个python的交互式shell,内置了很多有用的功能和函数。PyCharm是一种PythonIDE,带有一整套可以帮助用户在使用Python语言开发时提高其效率的工具,比如调试、语法高亮、Project管理、代码跳转、智能提示、自动完成、单元测试、版…

  • FastCGI简介

    FastCGI简介FastCGI实际上是以CGI变化而来的。因此,首先要了解CGI,下面通过介绍FastCGI来详细了解。CGI是一个协议,他描述了web服务器(nginx)和应用程序网关(php,python,等等)之间的信息交换。在实践中,当web服务器收到一个应该转发到该程序网关的请求时,只是简单的执行所需的命令(所需的应用程序)。客户端请求的详细信息通过命令行参数或环境变量来传递,然而实际的数据

  • c++ 静态函数_c语言if结构格式

    c++ 静态函数_c语言if结构格式1、对象与对象之间的成员变量是相互独立的.要想共用数据,则需要使用静态成员或静态方法2、只要在类中声明静态成员变量,即使不定义对象,也可以为静态成员变量分配空间,进而可以使用静态成员变量.(因为静态成员变量在对象创建之前就已经被分配了内存空间)3、静态成员变量虽然在类中,但它并不是随对象的建立而分配空间的,也不是随对象的撤销而释放(一般的成员在对象建立时会分配空间,在对象撤销时会释放…

发表回复

您的电子邮箱地址不会被公开。

关注全栈程序员社区公众号