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

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

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

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • 基于java的选课系统课程设计_java学生管理系统界面设计

    基于java的选课系统课程设计_java学生管理系统界面设计Java课程设计_学生选课管理系统需求分析本数据库的用户主要是学生,通过对用户需求的收集和分析,获得用户对数据库的如下要求。1.信息需求学生信息:学号,姓名,性别,专业登陆信息:账号,密码课程信息:课程号,课程名,选课人数,选课容量,任课老师选课信息:课程号,学生学号登录信息:账号、密码2.功能需求系统为学生建立登陆信息,学生进入系统前需要身份验证,用户名、密码输入正确后方可进入系统。在系统中,用户可以在界面中看到本人的基本信息,也可以对课程信息表和个人选课信息表进行查看、以及

    2022年8月31日
    6
  • Pycharm自动调整代码格式的快捷键Alt+Ctrl+L

    Pycharm自动调整代码格式的快捷键Alt+Ctrl+L1、代码自动填充空格2、自动对齐代码3、符合PEP8规范

    2025年7月13日
    4
  • BootStrap Validator入门

    BootStrap Validator入门目录官网使用效果认识 bootstrapval 初级用法简单使用官网官网 http bootstrapval com 源码下载地址 https github com nghuuphuoc bootstrapval 使用效果认识 bootstrapval 来看 bootstrapval 的描述 T

    2025年10月27日
    3
  • Python scikit-learn (metrics): difference between r2_score and explained_variance_score?

    Python scikit-learn (metrics): difference between r2_score and explained_variance_score?

    2021年11月21日
    49
  • python保留小数位数_python小数点保留三位

    python保留小数位数_python小数点保留三位https://www.luogu.org/problemnew/show/P14221.round()内置方法a=int(input())sum=0if(a>=401):sum+=(a-400)*0.5663a=400if(a>=151):sum+=(a-150)*0.4663a=150sum+=a*0.4…

    2022年8月11日
    5
  • 舵机控制原理详解「建议收藏」

    舵机控制原理详解「建议收藏」控制信号由接收机的通道进入信号调制芯片,获得直流偏置电压。它内部有一个基准电路,产生周期为20ms,宽度为1.5ms的基准信号,将获得的直流偏置电压与电位器的电压比较,获得电压差输出。最后,电压差的正负输出到电机驱动芯片决定电机的正反转。当电机转速一定时,通过级联减速齿轮带动电位器旋转,使得电压差为0,电机停止转动。舵机的控制一般需要一个20ms左右的时基脉冲,该脉冲的高电平部

    2022年6月15日
    37

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

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