Golang网页下载示例


package main

/*
 * 中文编码问题
 */

import (
	"errors"
	"flag"
	"fmt"
	query "github.com/PuerkitoBio/goquery"
	"golang.org/x/text/encoding/simplifiedchinese"
	"io/ioutil"
	"net/http"
	"os"
	"path/filepath"
	"runtime"
	"strings"
	"sync"
)


var (
	np = runtime.NumCPU()
	_  = runtime.GOMAXPROCS(np)
)

var wg sync.WaitGroup

type Folder struct {
	Url string
	Dir string
}

type File struct {
	Url  string
	Dir  string
	Name string
}


func checkErr(err error) {
	if err != nil {
		fmt.Printf("%v\n", err.Error())
		os.Exit(1)
	}
}


func decodeToGBK(text string) (string, error) {
	dst := make([]byte, len(text)*2)
	tr := simplifiedchinese.GB18030.NewDecoder()
	nDst, _, err := tr.Transform(dst, []byte(text), true)
	if err != nil {
		return text, err
	}
	return string(dst[:nDst]), nil
}


func printEach(index int, item *query.Selection) {
	fmt.Println("Selection: ", item.Text())
}


func isDir(path string) bool {
	return strings.HasSuffix(path, "/")
}


func makeFolder(item *query.Selection, url, dir string) (f *Folder, err error) {
	tx := item.Text()
	href, ok := item.Attr("href")
	name, err := decodeToGBK(tx)
	if err != nil {
		return
	}
	if !ok {
		err = errors.New("makeFolder : " + tx + " href属性不存在")
		return
	}
	f = &Folder{Url: url + href, Dir: filepath.Join(dir, name)}
	return
}


func makeFile(item *query.Selection, url, dir string) (f *File, err error) {
	tx := item.Text()
	href, ok := item.Attr("href")
	if !ok {
		err = errors.New("makeFile : " + tx + " href属性不存在")
		return
	}
	name, err := decodeToGBK(tx)
	if err != nil {
		return
	}
	f = &File{Url: url + href, Dir: dir, Name: name}
	return
}


func crawl(url, localDir string) {
	doc, err := query.NewDocument(url)
	// checkErr(err)
	if err != nil {
		fmt.Printf("%v\n", err.Error())
		return
	}

	items := doc.Find("a")

	dir := localDir

	if !strings.HasSuffix(url, "/") {
		url += "/"
	}

	crawlEach := func(i int, item *query.Selection) {
		tx := item.Text()
		if isDir(tx) {
			folder, err := makeFolder(item, url, dir)
			if err != nil {
				fmt.Printf("%v\n", err.Error())
				return
			}
			wg.Add(1)
			go crawlFolder(folder)
		} else {
			file, err := makeFile(item, url, dir)
			if err != nil {
				fmt.Printf("%v\n", err.Error())
				return
			}
			download(file)
		}
	}

	items.Each(crawlEach)
}


func download(file *File) {
	dir := file.Dir
	url := file.Url
	name := file.Name

	if err := os.MkdirAll(dir, os.ModePerm); os.IsExist(err) {
		fmt.Printf("%x is exist\n", dir)
	} else {
		os.Chmod(dir, os.ModePerm)
	}
	resp, err := http.Get(url)
	if err != nil {
		fmt.Printf("%v\n", err.Error())
		return
	}
	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Printf("%v\n", err.Error())
		return
	}

	fp := string([]rune(filepath.Join(dir, name)))

	err = ioutil.WriteFile(fp, body, 0777)
	if err != nil {
		fmt.Printf("%v fp:[%v]\n", err.Error(), fp)
		return
	}
	fmt.Printf("Download: %+v\n", file)
}


func crawlFolder(folder *Folder) {
	url := folder.Url
	dir := folder.Dir

	crawl(url, dir)
	wg.Done()
}


func main() {
	host := flag.String("host", "http://localhost:8000", "HTTP服务地址Host")
	location := flag.String("locate", "E:/Crawler下载文件", "本地文件系统绝对路径")
	flag.Parse()
	crawl(*host, *location)
	wg.Wait()
}





转载于:https://my.oschina.net/dexterman/blog/484516

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值