python爬虫和golang爬虫性能对比_使用 Golang 写爬虫经验总结

模拟登录

模拟登录最重要的是保存cookies的状态,例如在填写验证码的页面,服务器会传给客户端一个sessionID保存在cookies中,客户端在提交用户账户和验证码等信息时,需要连同这个cookies一起提交,否则服务器就无法判断两次请求是否为同一个客户端,从而导致验证码验证失败。

在Golang中可以使用CookieJar管理cookies,在创建http.Client的对象时,传入一个非空的CookieJar对象即可。设置了之后,Golang在收到服务器的响应之后,会自动把响应头中的cookies信息保存到CookieJar中,在下次发起请求时,自动从CookieJar中取出cookies信息放到请求头中。

// &cookiejar.Options{PublicSuffixList: publicsuffix.List},这是为了可以根据域名安全地设置cookies

cookieJar, err := cookiejar.New(&cookiejar.Options{PublicSuffixList: publicsuffix.List})

if err != nil {

panic(err)

}

client = http.Client{Jar: cookieJar, Timeout: time.Second * 3}

POST提交

GET提交方式很简单,直接拼接字符串就行了。POST提交需要一个可读的(io.Reader)请求体body,body中是形如a=b&c=d格式的查询字符串(字节切片)。可以借助url.Values方便的生成查询字符串,它本质是一个map[string][]string,提供了Set,Add等方法,让操作这个map更简单。

params := url.Values{}

// 添加参数

params.Add("memberAccount", "xxx")

// 添加sha1后的参数

params.Add("memberUmm", fmt.Sprintf("%x", sha1.Sum([]byte("xxxx"))))

params.Add("check", captcha)

params.Add("rememberMe", "on")

// 1.必须设置正确的Content-Type,否则服务器无法正确识别参数

// 2.params.Encode()生成查询字符串,然后用string.NewReader包裹这个字符串使其可读

res, err := client.Post("https://www.example.com/login.json", "application/x-www-form-urlencoded", strings.NewReader(params.Encode()))

if err != nil {

return "", err

}

// 记得关闭

defer res.Body.Close()

上传文件

上传文件需要借助multipart.Writer向请求体中写入相应的数据,使用multipart.NewWriter生成这样的一个写入器,它接收一个io.Writer作参数,这个参数即我们的表单体body,body除了需要可写,还要可读(让httpClient读取参数发送到服务器),并且它是流式的,所以选用bytes.Buffer,一个可读写大小可变的字节流缓冲器。

body := new(bytes.Buffer)

// 创建body的写入器

mulWriter := multipart.NewWriter(body)

写入普通字段

// 直接调用writeField方法即可,参数1是参数名,参数2是参数值

err := mulWriter.WriteField("user_name", "xxx")

if err != nil {

return "", err

}

写入文件字段

要写入文件,需要先调用CreateFormFile创建一个文件内容写入器,再通过写入器写入文件的内容

// 创建文件写入器,并指明文件参数名和参数值

fileWriter, err := mulWriter.CreateFormFile("upload", filepath.Base(filename))

if err != nil {

return "", err

}

// 打开需要上传的文件

file, err := os.Open(filename)

if err != nil {

return "", err

}

defer file.Close()

// 复制文件内容到写入器

_, err = io.Copy(fileWriter, file)

if err != nil {

return "", err

}

// 记得关闭,让缓冲区的内容写入body中

err = mulWriter.Close()

if err != nil {

return "", err

}

res, err := client.Post("http://v1-http-api.jsdama.com/api.php?mod=php&act=upload", mulWriter.FormDataContentType(), body)

上面例子的最后一行,必须使用FormDataContentType()方法获取正确的Content-Type,而不能自己写multipart/form-data,这是因为boundary是随机生成的,这个必须由Golang告诉我们正确的值。boundary即表单体中分隔每个参数的一个标志位,如下图:

使用Fiddler调试程序

使用Fiddler抓包可以让我们方便的看到程序提交到服务器的数据格式,使得调试和修改程序更加简单。Fiddler相当于一个正向代理服务器,启动后,它会把IE的代理服务器设置为http://127.0.0.1:8888 ,即Fiddler默认的代理地址,这样所有浏览器的请求都会先通过Fiddler,再由Fiddler转发出去,实现抓包。

但是上面的机制只对系统的浏览器有效,要对其他程序也生效,需要单独的设置程序的代理。

Golang设置代理比较简单,只需要增加一个环境变量设置即可,可以修改系统的环境变量,也可以通过代码动态添加。

// 设置httpClient的代理

os.Setenv("HTTP_PROXY", "http://127.0.0.1:8888")

解决HTTPS解密失败的问题

如果Fiddler出现无法解密HTTPS请求,看不到原始请求数据的情况,可以尝试重新安装Fiddler的根证书来解决。具体操作:

打开Fiddler,依次点击菜单Tools->Options,打开设置对话框,点击选中"HTTPS"面板

取消“Decrypt HTTPS traffic”的选中状态,点击“Actions”按钮,点击“Reset All Certificates”,之后会弹出确认框问你是否要删除当前的证书并创建新的证书,一路允许即可

本作品采用《CC 协议》,转载必须注明作者和本文链接

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值