• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

使用Go语言(golang)写个简单的爬虫

原作者: [db:作者] 来自: [db:来源] 收藏 邀请

上次用Scala写了个爬虫。最近在闲工夫之时,学习Go语言,便用Go移植了那个用Scala写的爬虫,代码如下:

package main

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

var (
	ptnIndexItem    = regexp.MustCompile(`<a target="_blank" href="(.+\.html)" title=".+" >(.+)</a>`)
	ptnContentRough = regexp.MustCompile(`(?s).*<div class="artcontent">(.*)<div >.*`)
	ptnBrTag        = regexp.MustCompile(`<br>`)
	ptnHTMLTag      = regexp.MustCompile(`(?s)</?.*?>`)
	ptnSpace        = regexp.MustCompile(`(^\s+)|( )`)
)

func Get(url string) (content string, statusCode int) {
	resp, err1 := http.Get(url)
	if err1 != nil {
		statusCode = -100
		return
	}
	defer resp.Body.Close()
	data, err2 := ioutil.ReadAll(resp.Body)
	if err2 != nil {
		statusCode = -200
		return
	}
	statusCode = resp.StatusCode
	content = string(data)
	return
}

type IndexItem struct {
	url   string
	title string
}

func findIndex(content string) (index []IndexItem, err error) {
	matches := ptnIndexItem.FindAllStringSubmatch(content, 10000)
	index = make([]IndexItem, len(matches))
	for i, item := range matches {
		index[i] = IndexItem{"http://www.yifan100.com" + item[1], item[2]}
	}
	return
}

func readContent(url string) (content string) {
	raw, statusCode := Get(url)
	if statusCode != 200 {
		fmt.Print("Fail to get the raw data from", url, "\n")
		return
	}

	match := ptnContentRough.FindStringSubmatch(raw)
	if match != nil {
		content = match[1]
	} else {
		return
	}

	content = ptnBrTag.ReplaceAllString(content, "\r\n")
	content = ptnHTMLTag.ReplaceAllString(content, "")
	content = ptnSpace.ReplaceAllString(content, "")
	return
}

func main() {
	fmt.Println(`Get index ...`)
	s, statusCode := Get("http://www.yifan100.com/dir/15136/")
	if statusCode != 200 {
		return
	}
	index, _ := findIndex(s)

	fmt.Println(`Get contents and write to file ...`)
	for _, item := range index {
		fmt.Printf("Get content %s from %s and write to file.\n", item.title, item.url)
		fileName := fmt.Sprintf("%s.txt", item.title)
		content := readContent(item.url)
		ioutil.WriteFile(fileName, []byte(content), 0644)
		fmt.Printf("Finish writing to %s.\n", fileName)
	}
}

  代码行数比Scala版的有一定增加,主要原因有以下几方面原因:
1 golang 重视代码书写规范,或者说代码格式,很多地方写法比较固定,甚至比较麻烦。比如就算是if判断为真后的执行语句只有一句话,按照代码规范,也要写出带大括号的三行,而在Scala和很多其他语言中,一行就行;
2 golang 的strings包和regexp包提供的方法并不特别好用,特别是和Scala相比,使用起来感觉Scala的正则和字符串处理要舒服的多;
3 scala版的爬虫里面用到了Scala标准库中的实用类和方法,它们虽然不是语法组成,但用起来感觉像是语法糖,这里很多方法和函数式编程有关,golang的函数式编程还没有去仔细学习。

  当然golang版的爬虫也有一个优势,就是编译速度很快,执行速度在现在的写法里面体现不出优势;golang的特性goroutine在这里没有用到,这段代码今后会不断改进。


鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
上一篇:
Go语言中的struct的初始化。发布时间:2022-07-10
下一篇:
Go语言:同个包下不同文件不能互相调用函数发布时间:2022-07-10
热门推荐
热门话题
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap