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)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • jquery ajax中success中的跳转问题

    jquery ajax中success中的跳转问题注意起来一个情况:ajax+submit+同步—-就是你用ajax请求服务器,而且用的是同步的方式,并且你是通过点击了type类型为submit的按钮来触发这个ajax。这个时候,首先你点击了submit,它会提交表单,但是由于你用了ajax的同步操作,submit的提交被阻塞,ajax先执行,这个时候,如果你在ajax的回调函数(如:success)中写了document.locatio…

    2022年6月13日
  • CultureInfo

    CultureInfo // ==++==// //   //    Copyright (c) 2002 Microsoft Corporation.  All rights reserved.//   //    The use and distribution terms for this software are contained in the file//  

    2022年6月19日
  • 新概念英语第三册 阅读「建议收藏」

    新概念英语第三册 阅读「建议收藏」新概念英语第三册Lesson1 ApumaatlargePumasarelarge,cat-likeanimalswhicharefoundinAmerica.WhenreportscameintoLondonZoothatawildpumahadbeenspottedforty-fivemilessouthofLondon,

    2022年11月1日
  • pycharm2019.3.3激活成功教程_pycharm字体推荐

    pycharm2019.3.3激活成功教程_pycharm字体推荐PyCharm是由著名的JetBrains公司所打造的一款功能强大的PythonIDE,它具有一般IDE都具备的功能,并且使用起来非常方便好用。最近需求PyCharm激活码的网友非常多,小编就在这里给大家分享一下PyCharm2019最新可用的激活注册码。激活Pycharm专业版的方法有很多,小编在这里主要给大家分享最有效的两种,一种是使用最新可用的注册激活码,一种是使用激活成功教程补丁的方法,这种方法…

    2022年8月25日
  • 双线性插值(Bilinear Interpol)原理及应用

    双线性插值(Bilinear Interpol)原理及应用在很多神经网络上采样过程中会用到双线性插值,其为基础的图像resize操作。以前一直没时间仔细研究,今天探究并记录一下原理和自己的理解。一、什么是插值插值指两个方面:一是在数学上,在离散数据的基础上补插连续函数,使得这条连续曲线通过全部给定的离散数据点;二是在图像处理上面,是利用已知邻近像素点的灰度值或RGB中的三色值产生未知像素点的灰度值或RGB三色值,目的是由原始图像再生出具有更高分辨率的图像。通俗一点理解就是已知推导未知,从而强化图像,具体效果如图1所示。…

    2022年6月1日
  • jsonschema校验json数据_xml schema校验

    jsonschema校验json数据_xml schema校验ajv使用在使用前,需要知道json-schema是什么。json-schemajson-schema是一个用来描述json数据格式。ajvajv是一个校验json-schem

    2022年8月2日

发表回复

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

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