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()
}
时间: 2024-10-09 15:16:32

Golang网页下载示例的相关文章

爬虫学习——网页下载器和urllib2模块

什么是网页下载器? 一.网页下载器是爬虫的核心组件 二.常用的python网页下载器有urlilib2基础模块和requests第三方插件两种 urllib2支持功能:1.支持直接url下载:2.支持向网页直接输入的数据:3.支持需要登陆网页的cookie处理:4.需要代理访问的代理处理 三.urllib2的三种下载方法 方法一.直接下载法 相应代码如下: #-*-coding:utf-8-*- #调用urllib2模块 import urllib2 #直接请求 response=urllib2

神奇的go语言(网页下载)

[ 声明:版权所有,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 目前,网上关于网页爬行的代码很多.但是,自从看了go语言的web下载代码之后,我才发现原来它的网页下载代码才是最简单的.不信的话,大家可以看一下, package main import( "fmt" "log" "net/http" "os" ) func main(){ resp,err:=http.Get("

Android之——断点下载示例

转载请注明出处:http://blog.csdn.net/l1028386804/article/details/46897641 在上一篇博文<Android之--多线程下载示例>中,我们讲解了如何实现Android的多线程下载功能,通过将整个文件分成多个数据块,开启多个线程,让每个线程分别下载一个相应的数据块来实现多线程下载的功能.多线程下载中,可以将下载这个耗时的操作放在子线程中执行,即不阻塞主线程,又符合Android开发的设计规范. 但是当下载的过程当中突然出现手机卡死,或者网络中断

用 python 实现一个多线程网页下载器

今天上来分享一下昨天实现的一个多线程网页下载器. 这是一个有着真实需求的实现,我的用途是拿它来通过 HTTP 方式向服务器提交游戏数据.把它放上来也是想大家帮忙挑刺,找找 bug,让它工作得更好. keywords:python,http,multi-threads,thread,threading,httplib,urllib,urllib2,Queue,http pool,httppool 废话少说,上源码: 1 # -*- coding:utf-8 -*- 2 import urllib,

IOS开发网络篇之──ASIHTTPRequest下载示例(支持断点续传)

IOS开发网络篇之──ASIHTTPRequest下载示例(支持断点续传) 网络ios文件管理器attributespathurl 在工程中,我们会常常遇到需要下载的程序,比如下载在线音乐.下载图片等等,今天我将介绍一下利用ASIHTTPRequest的下载示例,支持断点续传,利用ASIHTTPRequest下载以及断点续传的原理在我的博客:http://blog.csdn.net/pjk1129/article/details/6575588中有具体的介绍,今天重点介绍如何实现,废话少说,开始

[IOS_HTTP]ASIHTTPRequest下载示例(支持断点续传)

在工程中,我们会常常遇到需要下载的程序,比如下载在线音乐.下载图片等等,今天我将介绍一下利用ASIHTTPRequest的下载示例,支持断点续传,利用ASIHTTPRequest下载以及断点续传的原理在我的博客:http://www.cnblogs.com/webapplee/p/3784599.html 中有具体的介绍,今天重点介绍如何实现,废话少说,开始正文: 一.创建网络请求队列 首先,创建网络请求队列,如下: ASINetworkQueue   *que = [[ASINetworkQu

JSP中文件的上传于下载示例

一.文件上传的原理 1.文件上传的前提: a.form表单的method必须是post b.form表单的enctype必须是multipart/form-data(决定了POST请求方式,请求正文的数据类型) 注意:当表单的enctype是multipart/form-data,传统的获取请求参数的方法失效. 请求正文:(MIME协议进行描述的,正文是多部分组成的) -----------------------------7dd32c39803b2 Content-Disposition:

第5章 网页下载器和urllib2模块

网页下载器:将互联网上URL对应的网页下载到本地的工具 通过网页下载器将互联网中的url网页,存储到本地或内存字符串 python有哪几种网页下载器? 1.urllib2  python官方基础模块 2.requests   python第三方包更强大 urllib2下载网页方法1:最简洁方法 url-------------------------->urllib2.urlopen(url) 代码: import urllib2 /#直接请求 response = urllib2.urlopn

制作IOS企业版网页下载

有时候我们下载苹果的应用程序时不是从AppStore下载的.而是从XX网上下载的.那我们如何将苹果的应用程序IPA文件放到自己的官网上,然后供用户下载了.这样就不需要等待慢长的审核过程, 使用过android的朋友可能就会想,这不简单,直接放在服务器上,提供一个下载地址就不可以下载安装了吗? 你答对了一半,下载到手机上是没有问题,但能像apk 那样单击安装吗?当然不能.那怎么办了,过程还是有点复杂,接下来我将step-by-step的讲解一下. Step1:  配置plist文件 , 基于下面的