GOlang爬虫学习

2020年3月5日 0 作者 y1nhui

前言

学一波golang的爬虫啥的,写写脚本

在安装依赖的时候,因为不可抗拒原因导致无法直接安装对应依赖。所以可以直接去github上把东西下下来放到src下对应的文件夹里
对了,还有个叫go mod的东西

内容

flag

在用python脚本的时候,经常可以用到这种东西python dirsearch_master -u "www.exp.com" -e *
学c的时候我记得我学过这东西,但是没怎么用过就记不清了,于是golang这里也不知道叫啥。
咨询了一位大佬后知道了对命令参数进行解析。而golang标准库提供了一个包:flag,可以方便解析,那么很明显,接下来的一部分板块是给flag包的。
flag有两种用于绑定变量的函数,一种是typeVar如BoolVar一种是type,如Bool,两种用法相似,不过一个是返回保存了该flag指的指针,一个是将flag的值保存到p指向的变量。

示例:

flag.BoolVar(&h,"h",false,"hhhhhhhh")
h = flag.Bool("h",false,"hhhhhhhh")

这两个是一样的

然后想写一个-h的帮助也很简单,定义了-h后,使用flag.Usage()来输出,他的作用是打印到标准错误输出一个使用信息,记录了所有注册的flag。一般是输入了一个不存在的参数,然后报错运行了它,但是我们可以手动让它出现,来实现-help的功能。该函数是通过name指的内容来排序输出的

而传入的值,也是直接使用,而不需要使用a.value之类的方法。
比如代码:

package main

import (
"flag"
"fmt"
)

var u String
funv init() {
    flag.StringVar(&u,"u","","Target's url")
}
func main() {
    flag.Parse()
    fmt.Println(u)
}

3FucWV.png
而如果有其他的参数要传参,直接在后面跟上就行
比如:go run test.gp -u aaa -d bbb
那。。。感觉flag需要学的就没了,继续下一步

net/http

既然是要爬虫,那net肯定躲不掉的。。。
go有个很简单的请求方式:http.Get、http.Post不过这种不能调具体参数。
对了,请求完后需要手动关闭回复的主体。
defer resp.Body.Close()

要管理HTTP客户端的头域、重定向策略和其他设置,创建一个Client
要管理代理、TLS配置、keep-alive、压缩和其他设置,创建一个Transport

具体参照标准库:https://studygolang.com/pkgdoc

goquery

安装:go get github.com/PuerkitoBio/goquery

还有对html分析的,就要这个了
goquery似乎是没有请求的,他是在net包请求后,直接解析他的body。
比如:

resp,err := http.Get(url)
if err != nil {
    panic(err)  
}
doc,err := goquery.NewDocumentFromReader(resp,Body)

这样就可以在请求玩后直接解析html。需要进行元素选择的话,使用Find函数

进行find的时候,建议拼接each语句,将find的值迭代输入each中的selection参数,否则如果直接输出会导致格式混乱,而且一口气输出全部结果

iconv-go

这个就提一句,为了防止乱码,使用iconv-go转码
utfBody,err := iconv.NewReader(res.Body,"gb2312","utf-8")
将编码从gb2312转为utf8

#regexp
golang内置的正则包
首先说一下,因为python里面经常看到用原生字符串+多行字符串来储存正则表达式,为了方便golang也这样放得了。用反引号可以直接完成以上两个愿望

` awfaw
afwaf
afa
`

这样,然后记得用strings.replace去一下换行符和空格
先建立一个解析字符串出来的用于匹配的正则表达式(相当于新建一个对象吧)

reg := regexp.Mustcompile(ruler)

这里一开始我想让ruler = 的,但是这个函数返回的是一个*Regexp,而不是strings型,会错误。

之后 reg.FindAllString之类的,注意这种函数会有两个参数,第一个是检索的字符串,第二个是int型,指从何处开始。

写的时候还会发现golang木得in这类判断字段是否在切片内的东西,需要自己写个函数因为传入值类型不确定,所以可以直接用interface()来代表一切。

然后如果查询次数比较多的话,就用map。同步维护一个map,直接查map。同时维护
一个ID->*struct  的map 
一个[]*struct
用channel实现一个互斥锁就OKle
同步库里有个线程安全的map
或者用读写锁
互斥锁 读写锁 自旋锁 信号量
PV原子操作

##net/url
url包提供的url类型:

type URL struct {
Scheme   string //协议 即http、https
Opaque   string// 编码后的不透明数据
User *Userinfo // 用户名和密码信息
Host string// host或host:port
Path string //路径
RawQuery string // 编码后的查询字符串,没有'?'
Fragment string // 引用的片段(文档位置),没有'#'
}

url包有两个解析字符串为url结构体的函数
ParseRequestURIParse不过没看出来ParseRequest的意义。官方描述:

ParseRequestURI函数解析rawurl为一个URL结构体,本函数会假设rawurl是在一个HTTP请求里,因此会假设该参数是一个绝对URL或者绝对路径,并会假设该URL没有#fragment后缀。(网页浏览器会在去掉该后缀后才将网址发送到网页服务器)

感觉一般情况下,需要的只有path、host、scheme和RawQuery