爬虫开发

引入

在具体讲解爬虫知识之前,我们首先简单回顾下前面Http编程。

  1. 服务器端:利用net/http包编写一个服务器,让浏览器请求我们的服务器。

    基本流程:

    • 接受请求后分析协议

    • 回发相应数据给浏览器。

  2. 客户端:利用net/http包编写一个客户端(用于模拟浏览器行为), 向互联网上现有的服务器发送请求,获取服务器上的数据。

    基本的流程:

    • 构建、发送请求链接

    • 获取服务器返回的响应数据

    • 过滤、保存、使用得到的数据

    • 关闭请求链接。

小提示:我们利用客户端程序是获取的服务器数据和利用浏览器获取的数据是一模一样的,只不过浏览器会把文件按照一定的格式显示出来而已。

爬取百度贴吧

爬取策略分析

段子爬取

package main

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

func main(){
	StartWork(1, 20)
}

func StartWork(start, end int){
	gotIt := make(chan int)
	for i := start; i <= end; i++{
		url := "https://www.pengfu.com/xiaohua_" + strconv.Itoa(i) + ".html"
		go SpiderOne(url, i, gotIt)
	}

	for i := start; i <= end; i++{
		index := <-gotIt
		fmt.Printf("第%d页爬取ok\n", index)
	}
}

func SpiderOne(url string, index int, gotIt chan int){
	//获取网络请求的结果
	content, err := HttpGet(url)
	if err!= nil{
		fmt.Println("spider one err:", err)
		return
	}

	//提取段子标题和内容
	matchedBytes := ExtractInfo(content, `<h1 class="dp-b"><a href=(?s:.*?)>(?s:(.*?))</a>(?s:.*?)<div class="content-img clearfix pt10 relative">(?s:(.*?))</div>`)

	//拼接段子标题和内容,并写入文件
	fileContent := make([]byte, 0)
	for _, oneMatched := range matchedBytes{
		fileContent = append(fileContent, []byte("\r\n标题:")...)
		fileContent = append(fileContent, oneMatched[1]...)
		fileContent = append(fileContent, []byte("\r\n内容:")...)
		fileContent = append(fileContent, oneMatched[2]...)
	}
	fileName := "D:/spiderResult/" + strconv.Itoa(index) + ".txt"
	Save2File(fileContent, fileName)
	gotIt <- index
}

/****************************************************
*函数功能:
	获取给定的url指向的网络资源,返回结果的字节切片和遇到的错误
*****************************************************/
func HttpGet(url string) (result []byte, err error){
	resp, err := http.Get(url)
	if err != nil{
		fmt.Println("http get err:", err)
		return
	}
	defer resp.Body.Close()

	content, err := ioutil.ReadAll(resp.Body)
	if err != nil{
		fmt.Println("read all err:", err)
		return
	}

	return content, nil
}

/****************************************************
*函数功能:
*	把content内的字节切片存储至path指向的文件中,返回遇到的错误
****************************************************/
func Save2File(content []byte, path string,)(err error){
	err = ioutil.WriteFile(path, content, 0666)
	if err != nil{
		fmt.Println("ioutil WriteFile err:", err)
	}

	return
}

/*****************************************************
*函数功能:
*	从content的字节切片中提取符合re正则表达式的文本输出
******************************************************/
func ExtractInfo(content []byte, re string)(matchedBytes [][][]byte){
	r := regexp.MustCompile(re)
	matchedBytes = r.FindAllSubmatch(content, -1)
	return
}

爬取豆瓣

	//提取电影名称、导演、评分、评论人数、短评
	re := `<img width="100" alt="(.*?)"(?s:.*?)<p class="">(?s:(.*?))</p>(?s:.*?)<span class="rating_num" property="v:average">(?s:(.*?))</span>(?s:.*?)<span>(?s:(.*?))人评价</span>(?s:.*?)<span class="inq">(?s:(.*?))</span>`
	contents := ExtractInfo(re, rawContent)

	//替换网页中的特殊字符,组织最终的有用信息的字符串
	fileContent := ""
	for _, c := range contents{
		for i := 1; i < len(c); i++{
			temp := strings.TrimSpace(c[i])
			temp = strings.Replace(temp, "&nbsp", " ", -1)
			temp = strings.Replace(temp, "<br>", "\r\n", -1)
			switch  i {
			case 1:
				fileContent += "电影名称:"
			case 3:
				fileContent += "评分:"
			case 4:
				fileContent += "短评:"
			}
			fileContent= fileContent + temp + "\r\n"
		}
		fileContent += "\r\n"
	}

	//把最终生成的字符串写入对应文件
	Save2File(path ,fileContent)
	gotIt <- index

}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值