爬虫项目的应用范围很广泛
最近总结了一下爬虫的项目 并记录下来
爬虫的最终版为 分布式并发处理爬虫 但是我们分为三部分记录 首先是单任务版的爬虫记录
此次我们爬取的是珍爱网的公开内容 由于其他网址有可能涉及私密信息 所以选择相亲网站
声明 本人爬取的内容只供自己练习爬虫使用 不会以此牟利
首先看一下我们要爬取的网页界面
我们先从最终版本捋顺出单任务版本爬虫需要实现的功能
.获取并打印所有城市第一页用户的详细信息
这是我们需要或许的内容之一 各个城市的名称
先打印出网页的所有源代码
func main(){
//试探网页能否正常打开 若能则将网页内容以结构体指针方式返回
resp , err :=http.Get("http://www.zhenai.com/zhenghun")
if err != nil{
panic(err)
}
//程序结束时实现结构体指针关闭
defer resp.Body.Close()
//判断头部内容是否正确
if resp.StatusCode != http.StatusOK{
fmt.Println("Error StatusCode:", resp.StatusCode)
return
}
//获取字符串
s, err := ioutil.ReadAll(resp.Body)
if err != nil{
panic(err)
}
fmt.Printf("%s", s)
}
打印内容后我们的结果上面中文都是乱码 我们解决一下
func main(){
//试探网页能否正常打开 若能则将网页内容以结构体指针方式返回
resp , err :=http.Get("http://www.zhenai.com/zhenghun")
if err != nil{
panic(err)
}
//程序结束时实现结构体指针关闭
defer resp.Body.Close()
//判断头部内容是否正确
if resp.StatusCode != http.StatusOK{
fmt.Println("Error StatusCode:", resp.StatusCode)
return
}
//自动判断字符格式函数 详细讲解在函数体内
e := DetermineEncoding(resp.Body)
//将从网页中获取的结构体放入函数并告诉函数结构体内的字符格式 返回utf8格式
utf8Reader := transform.NewReader(resp.Body,e.NewDecoder())
//将结构体内容返回为byte
s, err := ioutil.ReadAll(utf8Reader)
if err != nil{
panic(err)
}
//打印utf8格式字符
fmt.Printf("%s", s)
}
//判断字符格式并返回
func DetermineEncoding(r io.Reader) encoding.Encoding{
//提取结构体内的前1024个字符
byte , err := bufio.NewReader(r).Peek(1024)
if err != nil{
panic(err)
}
//比较提取出来的字符进行判断
e, _, _:= charset.DetermineEncoding(byte,"")
//返回盘短值
return e
}
需要注意的是如果没有安装指定库 上面代码可能有的无法实现 我们安装库
一共是安装两个库
gopm get -g -v golang.org/x/text 是进行字符格式转换
gopm get -g -v golang.org/x/net/html 是字符类型自动判断
安装完成后指定路径会出现库文件gbk.go
现在我们来打印结果
现在我们正确的打印出网页源代码了
有了源代码之后 我们要筛选出对自己有用的信息
获取城市名称和连接的方法有
.使用css选择器
.使用xpath (与css类似)
.使用正则表达式
这里我用到的是正则表达式 在正式进行项目之前 我们回顾一下正则表达式
const text = `
My email is 8899666@qq.com
email1 is abc@def.org
email2 is kkk@qq.com
email3 is ddd@abc.com.cn
`
func main() {
//确定要寻找的目标及返回需要的字符段
re := regexp.MustCompile(`([a-zA-Z0-9]+)@([a-zA-Z0-9]+)(\.[a-zA-Z0-9.]+)`)
//返回二维数组 函数的作用是得到字符段并按要求返回需要的单个字符串
match := re.FindAllStringSubmatch(text,-1)
//循环打印每一段字符
for _, m := range match{
fmt.Println(m)
}
}
打印结果如下
regexp.MustCompile函数内的参数含义为 要用什么条件进行查找
[a-zA-Z0-9]括号内代表要查找的内容 大小写字母及数字 都是我们要查找的内容
([a-zA-Z0-9]) 中括号外面一层小括号代表 被小括号包括的所有内容都重新分配一段内容作为返回值
.*为查找全部内容包括空字符
.+为查找全部内容不包括空字符 字符为空则不打印
\.为转义字符 需要注意
回顾结束 下面我们在项目中使用
func main(){
//试探网页能否正常打开 若能则将网页内容以结构体指针方式返回
resp , err :=http.Get("http://www.zhenai.com/zhenghun")
if err != nil{
panic(err)
}
//程序结束时实现结构体指针关闭
defer resp.Body.Close()
//判断头部内容是否正确
if resp.StatusCode != http.StatusOK{
fmt.Println("Error StatusCode:", resp.StatusCode)
return
}
//自动判断字符格式函数 详细讲解在函数体内
e := DetermineEncoding(resp.Body)
//将从网页中获取的结构体放入函数并告诉函数结构体内的字符格式 返回utf8格式
utf8Reader := transform.NewReader(resp.Body,e.NewDecoder())
//将结构体内容返回为byte
s, err := ioutil.ReadAll(utf8Reader)
if err != nil{
panic(err)
}
//----------------------------------------------------------------------------------
//获取所需内容函数 |
printCityList(s) |
//----------------------------------------------------------------------------------
}
//判断字符格式并返回
func DetermineEncoding(r io.Reader) encoding.Encoding{
//提取结构体内的前1024个字符
byte , err := bufio.NewReader(r).Peek(1024)
if err != nil{
panic(err)
}
//比较提取出来的字符进行判断
e, _, _:= charset.DetermineEncoding(byte,"")
//返回盘短值
return e
}
//----------------------------------------------------------------------------------
//提取所需内容 如网页地址 城市名称 |
func printCityList(contents []byte){ |
//设置被提取者所需要的条件 |
re :=regexp.MustCompile(`<a href="(http://www.zhenai.com/zhenghun/[a-z0-9]+)"[^>]*>([^<]+)</a>`) |
//从网页文件中提取所需文件 |
matches := re.FindAllSubmatch(contents, -1) |
//打印所需内容 |
for _, m := range m