go爬虫,golang 爬取壁纸和图片其他信息保存入库

go以速度快(高并发)出名还是有道理的,在数据量越来越大的时代,程序的处理速度也得跟上,习惯了使用简单的python可远远不够,还是应该继续学习新知识。其实比起C语言来说,go还是简单很多的,虽然没有python那么容易上手,但是熟悉之后会喜欢上的。

package main
import (
    "bytes"
    "fmt"
    "io"
    "io/ioutil"
    "log"
    "mime/multipart"
    "net/http"
    "os"
    "strconv"
    "strings"
    "sync"
    "time"
    "github.com/PuerkitoBio/goquery"
)
var (
    path_url            = `https://wall.alphacoders.com/by_sub_category.php?id=333944&name=Genshin%20Impact&page=`
    pageStart    int    = 1                                  // 起始页
    page         int    = 1                                  // 爬取页数
    DownLoadPath string = "C:/Users/me/go/src/go_query/img/" // 图片下载存放地址
    wg           sync.WaitGroup
)
type imginfo struct {
    Title  string `json:"title"`
    Url    string `json:"url"`
    Width  string `json:"width"`
    Height string `json:"height"`
    Page   int    `json:"page"`
}
func main() {
    fmt.Println("从第几页开始")
    fmt.Scanln(&pageStart)
    fmt.Println("扫描页数")
    fmt.Scanln(&page)
    for i := pageStart; i < pageStart+page; i++ {
        wg.Add(1)
        getBody(i)
    }
    wg.Wait()
    fmt.Println("执行完毕,回车退出")
    var input string
    fmt.Scanln(&input)
}
//获取页面数据
func getBody(p int) {
    resp, err := http.Get(path_url + strconv.Itoa(p))
    if err != nil {
        log.Fatalf("status code error: %s", err)
    }
    defer resp.Body.Close()
    dom, err := goquery.NewDocumentFromReader(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    dom.Find(".boxgrid").Each(func(i int, s *goquery.Selection) {
        href, _ := s.Find("a").Attr("href")
        title, _ := s.Find("a").Attr("title")
        width, height := "0", "0"
        _imginfo := imginfo{
            Title:  title,
            Url:    href,
            Width:  width,
            Height: height,
            Page:   p,
        }
        getImgInfo(_imginfo)
    })
    wg.Done()
}
//获取图片详情
func getImgInfo(_imginfo imginfo) {
    url := "https://wall.alphacoders.com" + _imginfo.Url
    resp, err := http.Get(url)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    dom, err := goquery.NewDocumentFromReader(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    dom.Find(".center.img-container-desktop").Each(func(i int, s *goquery.Selection) {
        href, _ := s.Find("a").Attr("href")
        width, _ := s.Find("img").Attr("width")
        height, _ := s.Find("img").Attr("height")
        _imginfo.Url = href
        _imginfo.Width = width
        _imginfo.Height = height
        handleImg(_imginfo)
    })
}
// 处理图片方法
func handleImg(_imginfo imginfo) {
    fileName := getFilename(_imginfo.Url)
    result := DownloadFile(_imginfo, fileName)
    if result {
        fmt.Printf("已下载完毕: %s - %s - %s - %s \n", _imginfo.Url, _imginfo.Title, _imginfo.Width, _imginfo.Height)
    } else {
        fmt.Printf("下载失败 %v \n", _imginfo.Url)
    }
}
// 截取url名字
func getFilename(url string) (filename string) {
    lastIndex := strings.LastIndex(url, "/")
    filename = url[lastIndex+1:]
    timePrefix := strconv.Itoa(int(time.Now().UnixNano()))
    filename = timePrefix + "_" + filename
    return
}
//下载图片
func DownloadFile(_imginfo imginfo, filename string) bool {
    var err error
    resp, err := http.Get(_imginfo.Url)
    if err != nil {
        log.Fatal(err)
    }
    defer resp.Body.Close()
    bytes, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Fatal(err)
    }
    if _, err := os.Stat(DownLoadPath); os.IsNotExist(err) {
        os.Mkdir(DownLoadPath, 0777)
        os.Chmod(DownLoadPath, 0666)
    }
    filename = DownLoadPath + filename
    err = ioutil.WriteFile(filename, bytes, 0666)
    if err != nil {
        return false
    }
    postFile(_imginfo, filename, "http://127.0.0.1:9999/wp-admin/admin-ajax.php")
    return true
}
//数据提交
func postFile(_imginfo imginfo, filename string, target_url string) error {
    body_buf := bytes.NewBufferString("")
    body_writer := multipart.NewWriter(body_buf)
    fh, err := os.Open(filename)
    if err != nil {
        fmt.Println("error opening file")
        return err
    }
    defer fh.Close()
    body_writer.WriteField("action", "upload_wallpaper")
    body_writer.WriteField("width", _imginfo.Width)
    body_writer.WriteField("height", _imginfo.Height)
    body_writer.WriteField("title", _imginfo.Title)
    body_writer.CreateFormFile("file", filename)
    boundary := body_writer.Boundary()
    close_buf := bytes.NewBufferString(fmt.Sprintf("\r\n--%s--\r\n", boundary))
    request_reader := io.MultiReader(body_buf, fh, close_buf)
    req, err := http.NewRequest("POST", target_url, request_reader)
    if err != nil {
        return err
    }
    req.Header.Add("Content-Type", "multipart/form-data; boundary="+boundary)
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Printf("上传失败: %s\n", err)
        return err
    }
    ret, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        fmt.Printf("转换失败: %s\n", err)
        return err
    }
    defer resp.Body.Close()
    fmt.Printf("返回的状态码是: %v\n", resp.StatusCode)
    fmt.Printf("返回的信息是: %v\n", string(ret))
    return nil
}
赞 (0) or 分享 (0)