go获取html页面

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httputil"
)

func main(){
	// 使用http.Get函数,传入url,得到一个*Response和一个error
	res, err := http.Get("https://tieba.baidu.com/p/5524106374?red_tag=3108778011")
	// 内容都在res.Body下面,res.Body相当于一个io.Reader记得要关闭
	defer res.Body.Close()
	if err!=nil{
		fmt.Println("err=",err)
		return
	}
	// 使用ioutil.ReadAll,接收一个io.Reader,将res.Body读取出来,得到一个[]byte和一个error
	html,err := ioutil.ReadAll(res.Body)
	if err!=nil{
		fmt.Println("err=",err)
		return
	}
	// 这里的html是[]byte,使用string转化一下
	fmt.Println(string(html))
	/*
	截取一部分:
	<!DOCTYPE html><!--STATUS OK--><html><head><meta name="keywords" content="百度贴吧,椎名真白资源,白原,图高"/
	 */

	//上述方式获取的是html页面,我们还可以获取相应报文,使用httputil.DumpResponse,这个函数需要接收一个*Response和一个bool类型,所以这里直接传入*Response类型的res,和一个bool类型即可
	// bool类型表示是否将res.Body里面的内容Dump出来,这里传入true
	html1, err := httputil.DumpResponse(res, true)
	if err!=nil{
		fmt.Println("err=",err)
	}
	// 这里的html1依旧是一个[]byte,需要转成string
	fmt.Println(string(html1))
	/*
	HTTP/1.1 200 OK
	Transfer-Encoding: chunked
	Connection: keep-alive
	Content-Type: text/html; charset=UTF-8
	Date: Fri, 16 Nov 2018 08:26:50 GMT
	P3p: CP=" OTI DSP COR IVA OUR IND COM "
	Server: Apache
	Set-Cookie: TIEBA_USERTYPE=5c40c0e62e72fae312d68f2d; expires=Thu, 31-Dec-2020 15:59:59 GMT; path=/; domain=tieba.baidu.com
	Set-Cookie: wise_device=0; path=/
	Set-Cookie: BAIDUID=E09822172FC8F15E98583B8B2380A118:FG=1; expires=Sat, 16-Nov-19 08:26:50 GMT; max-age=31536000; path=/; domain=.baidu.com; version=1
	Tracecode: 16103786370354826762111616
	Tracecode: 16103786370976641034111616
	Vary: Accept-Encoding
	X-Xss-Protection: 1; mode=block
	 */

}

  

go进行post请求

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
)

func main(){
	//如何模拟登录,可以使用http.Post,接收三个参数
	//func Post(url, contentType string, body io.Reader) (resp *Response, err error)
	//contentType一般写"application/x-www-form-urlencoded"即可
	//body是请求体,类似于Python中requests.post里的data,但这里只能接收一个参数,而且还是io.Reader类型
	res,err:=http.Post("xxxxx", "application/x-www-form-urlencoded", strings.NewReader("phone=12345421"))
	defer res.Body.Close()
	if err!=nil{
		fmt.Println("err=",err)
	}
	body,_:=ioutil.ReadAll(res.Body)
	fmt.Println(string(body))

	//那么如何接收多个参数呢?
	//可以使用http.PostForm
	//func PostForm(url string, data url.Values) (resp *Response, err error)
	//这里的data才真正意义上相当于requests.post里面的data
	//为什么这里的value还需要加上{},url.Values就是这么定义的,type Values map[string][]string,需要传入一个切片
	res1,err1 := http.PostForm("xxxxxx", url.Values{"username":{"1245412154"}, "passwd":{"dadsadsadas"}})
	if err!=nil{
		fmt.Println("err1=",err1)
	}
	defer res1.Body.Close()
	body,_ = ioutil.ReadAll(res1.Body)
	fmt.Println(body)

}

  

以上就是go如何进行get和post请求,但是我们发现我们并没有加上请求头之类的,这样很容易被反爬虫,那么如何加上请求头之类的呢?

package main

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
)

func main(){
	url := "https://tieba.baidu.com/p/5524106374?red_tag=3108778011"
	//这里使用http.NewRequest
	//func NewRequest(method, url string, body io.Reader) (*Request, error)
	//请求头等乱七八糟的全加好了,但注意此时还没有真正去爬爬取,我们请求头还没加呢?
	res, err := http.NewRequest("GET", url,nil)
	if err!=nil{
		fmt.Println("err=",err)
		return
	}
	//使用NewRequest获得的res便可以添加cookies请求头之类的了
	//接收两个string,分别是key和value
	res.Header.Add("cookies","sessionid=5edb1f18c5a0cb334b42b2383c899e01")
	res.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36")
	//请求头等乱七八糟的全加好了,怎么让它去爬呢?
	client := &http.Client{}
	//直接Do一下就好了,表示让res去工作
	//func (c *Client) Do(req *Request) (*Response, error)
	//可以看到接收的是一个Request的指针类型,返回一个*Response和一个error
	//和http.Get的返回值一样
	res1, err := client.Do(res)
	//仍然使用ioutil.ReadAll读取
	body,_ := ioutil.ReadAll(res1.Body)
	fmt.Println(string(body))

	//同理post也是一样
	//这里body相当于requests.post里的params
	res, _ = http.NewRequest("GET", url, strings.NewReader("username=satori&password=123"))
	//注意这一句必须加上,否则post参数无法正常传递
	res.Header.Add("Content-Type", "application/x-www-form-urlencoded")
	//剩下的和get请求一样
}

  

实战演练

我们就将页面的所有图片爬取下来。

package main

import (
	"io/ioutil"
	"net/http"
	"regexp"
	"strconv"
	"sync"
)

func get_pic_url(url string, target_length int)[]string{
	req,_ := http.NewRequest("GET", url, nil)
	req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36")
	client := &http.Client{}
	res,_ := client.Do(req)
	//得到整个html页面,当然这里还是字节
	html,_:= ioutil.ReadAll(res.Body)
	//构建正则,用于匹配图片的url
	compile,_ := regexp.Compile(`<img.+?src="(.+?jpg)`)
	//查找匹配的图片url
	all_pic_url := compile.FindAllStringSubmatch(string(html), -1)
	//go的正则不好的一点就是,我们只想匹配括号里面的内容,但是它把整体也匹配出来了
	//也就是整体和括号里面的一起放到一个切片里面,需要我们通过索引去取
	//所以这里必须使用FindAllStringSubmatch,如果FindAllString,即便加了括号也只能匹配整体
	pic_url_array := []string{}  //存储图片url的切片
	for _,v:=range all_pic_url{
		//但不是所有url我们都要,有些是用户上传的表情,因为我们需要进行筛选
		//target_length就是我们想要的图片的url的长度,只有长度和target_length相等的url我们才要
		if len(v[1]) == target_length{
			pic_url_array = append(pic_url_array, v[1])
		}
	}
	return pic_url_array
}

//连接有了,下面我们下载图片
func download(pic_url_array []string){
	var wg sync.WaitGroup
	wg.Add(len(pic_url_array))
	for index,url := range pic_url_array{
		//这里并发下载
		go func(index int, url string) {
			req,_ := http.NewRequest("GET", url, nil)
			req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/69.0.3497.81 Safari/537.36")
			client := &http.Client{}
			res,_ := client.Do(req)
			//由于这里获取的是字节数组,正好我们也不需要转了,直接写入二进制b
			content,_ := ioutil.ReadAll(res.Body)
			ioutil.WriteFile(`C:\Users\Administrator\go\src\awesomeProject\pic\`+strconv.Itoa(index)+".jpg",content,0755)
			wg.Done()
		}(index, url)
	}
	wg.Wait()
}
func main(){
	target_length := len("https://imgsa.baidu.com/forum/w%3D580/sign=50b8de14898ba61edfeec827713597cc/af59f91b0ef41bd54ce3302a5ada81cb38db3d00.jpg")
	pic_url_array :=get_pic_url("https://tieba.baidu.com/p/5524106374?red_tag=3108778011", target_length)
	download(pic_url_array)
}

  

  

最新文章

  1. VirtualBox装ghost XP
  2. github android
  3. “SQLServerAgent当前未运行”问题解决
  4. access数据库多个left join示例
  5. 基于51单片机+DAC0832的信号发生器
  6. [原] Android持续优化 - 提高流畅度
  7. comboBox的多选框之疑难杂症——逗号篇
  8. Android Packaging Problem
  9. 高级I/O之readv和writev函数
  10. Android之fragment点击切换和滑动切换结合
  11. 极客”一词,来自于美国俚语“geek”的音译,一般理解为性格古怪的人
  12. C 文件直接包含
  13. .Net程序员学用Oracle系列(7):视图、函数、过程、包
  14. 批处理改hosts
  15. vmware 安装提示the msi failed
  16. PyCharm中设置字体大小
  17. 机器学习实战ch04 关于python版本所支持的文本格式问题
  18. 【Linux】常见公共DNS地址
  19. RBAC 权限设计(转载)
  20. ACPI:Memory错误解决办法

热门文章

  1. Drools 7.4.1.Final参考手册(六) 用户手册
  2. django类视图简单使用和源码解析
  3. 在Android Studio中创建(或添加)第一个Hello World应用程序
  4. JavaSE复习(二)集合
  5. Java基础——集合
  6. DES(Data Encryption Standard)数据加密标准
  7. [洛谷P1747]好奇怪的游戏
  8. hdu3068最长回文(Manacher算法)
  9. [Leetcode] remove element 删除元素
  10. [NOI2010]能量采集 解题报告