吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 2632|回复: 14
收起左侧

[讨论] golang爬虫

[复制链接]
redblue 发表于 2020-10-28 23:14
package main

import (
    "fmt"
    query "github.com/antchfx/xquery/html"
    "golang.org/x/net/html"
    "io/ioutil"
    "math/rand"
    "net/http"
    "os"
    "path/filepath"
    "strconv"
    "strings"
    "time"
)

var UA = []string{
    "Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:47.0) Gecko/20100101 Firefox/47.0",
    "Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)",
    "Mozilla/5.0 (Macintosh; U; Intel Mac OS X 10_6_8; en-us) AppleWebKit/534.50 (KHTML, like Gecko) Version/5.1 Safari/534.50",
    "Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; en) Presto/2.8.131 Version/11.11",
    "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 5.1; 360SE)",
}

func fetch(url string) string {
    //fmt.Println("Fetch Url", url)
    client := &http.Client{}
    //method参数 GET、POST要大写
    req, _ := http.NewRequest("GET", url, nil)
    index := rand.Intn(len(UA))
    req.Header.Set("User-Agent", UA[index])
    req.Header.Add("Referer", "https://www.mzitu.com/")
    rsp, err := client.Do(req)
    if err != nil {
        fmt.Println("Http get err: ", err)
        return ""
    }
    if rsp.StatusCode != 200 {
        fmt.Println("Http status code:", rsp.StatusCode)
        return ""
    }
    defer rsp.Body.Close()
    body, err := ioutil.ReadAll(rsp.Body)
    if err != nil {
        fmt.Println("Read error:", err)
        return ""
    }

    return string(body)
}

/**
* 下载图片
 */
func downloadImg(url string, dir string) {
    _, name := filepath.Split(url)
    fileName := filepath.Join(dir, name)
    data := fetch(url)
    err := ioutil.WriteFile(fileName, []byte(data), 0644)
    if err != nil {
        fmt.Println("ioutil.WriteFile err:", err)
    }
}

//获取页面中最大页码
func getMaxPage(url string, xpath string) int {
    result := fetch(url)
    root, err := query.Parse(strings.NewReader(result))
    if err != nil {
        panic(err)
    }
    maxPageNode := query.FindOne(root, xpath)
    maxPage := query.InnerText(maxPageNode)
    length, _ := strconv.Atoi(maxPage)
    return length
}

func getHtmlNode(url string, xpath string) *html.Node {
    result := fetch(url)
    root, err := query.Parse(strings.NewReader(result))
    if err != nil {
        fmt.Printf("query.Parse err:%s\n", err)
    }
    return query.FindOne(root, xpath)
}

func getHtmlNodes(url string, xpath string) []*html.Node {
    result := fetch(url)
    root, err := query.Parse(strings.NewReader(result))
    if err != nil {
        fmt.Printf("query.Parse err:%s\n", err)
    }
    return query.Find(root, xpath)
}

func main() {
    url := "https://www.mzitu.com/mm/"
    dir := "D:\\新建文件夹111"
    length := getMaxPage(url, "//div[@class='nav-links']/a[last()-1]")
    listPageUrl := url + "page/%d"
    for i := 1; i <= length; i++ {
        url = fmt.Sprintf(listPageUrl, i)
        imgListNodes := getHtmlNodes(url, "//ul[@id='pins']/li/a")
        for _, img := range imgListNodes {
            href := query.SelectAttr(img, "href")
            nameNode := query.FindOne(img, "//img")
            name := query.SelectAttr(nameNode, "alt")
            fmt.Printf("%s----%s\n", name, href)

            filePath := filepath.Join(dir, name)
            err := os.MkdirAll(filePath, 0777)
            if err != nil {
                fmt.Printf("os.MkdirAll err:%s\n", err)
            }
            //进入详情页
            maxImagePageInt := getMaxPage(href, "//div[@class='pagenavi']/a[last()-1]/span")
            for j := 1; j < maxImagePageInt; j++ {
                if j == 1 {
                    url = href
                } else {
                    url = href + "/" + strconv.Itoa(j)
                }
                imgUrlNode := getHtmlNode(url, "//div[@class='main-image']/p/a/img")
                imgUrl := query.SelectAttr(imgUrlNode, "src")
                fmt.Printf("download:%s\n", imgUrl)
                downloadImg(imgUrl, filePath)
                time.Sleep(500 * time.Millisecond)
            }
            time.Sleep(500 * time.Millisecond)
        }
    }
}

不多说,直接上代码,代码有点丑,莫笑。

免费评分

参与人数 1吾爱币 +1 收起 理由
熊猫拍板砖 + 1 建议在rand.intn前面加置随机数种子

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

头像被屏蔽
枫子树 发表于 2020-10-28 23:30
提示: 作者被禁止或删除 内容自动屏蔽
qaz152217 发表于 2020-10-29 00:01
thepoy 发表于 2020-10-29 00:02
很好啊,能想到用golang写爬虫,但没用到golang最优势的协程,是不是可以再改改?或者直接用colly吧。
a3322a 发表于 2020-10-29 07:30
不错,感谢分享!
wikiyc 发表于 2020-10-29 07:51
学习了,谢谢。
 楼主| redblue 发表于 2020-10-29 09:24
thepoy 发表于 2020-10-29 00:02
很好啊,能想到用golang写爬虫,但没用到golang最优势的协程,是不是可以再改改?或者直接用colly吧。

刚学,还不会,正在研究
为你一人 发表于 2020-10-29 09:29
保存图片时应该开启一个goroutine,不应该在主goroutine中保存图片,这样不能发挥go的优势,开启子goroutine后下载会更快
deanyang 发表于 2020-10-29 10:01
可以可以
萨卡卡 发表于 2020-11-11 17:31
学习了,谢谢分享
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-26 04:27

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表