您好,欢迎来到三六零分类信息网!老站,搜索引擎当天收录,欢迎发信息

golang爬虫的基本组成部分和编写方法

2024/3/22 1:04:19发布35次查看
随着互联网的普及与信息化的加速发展,越来越多的数据被存放在互联网上,因此网络爬虫已经成为许多人不可或缺的工具。其中,golang爬虫由于其简洁、高效和可扩展性,成为了许多程序员首选的爬虫编写语言。
本文将介绍golang爬虫的基本组成部分和编写方法。
一、golang爬虫的基本组成部分
url管理器(urlmanager)url管理器主要负责管理需要爬取的url队列,以及去重等相关操作。其主要包含以下功能:
添加url:将需要爬取的url添加到队列中;获取url:从url队列中获取待爬取的url;存储url:将已爬过的url存储下来;去重:防止重复爬取同一个url。网页下载器(downloader)网页下载器主要负责将url对应的网页下载到本地。它可以根据url的不同特点,采用不同的下载方式,如http、https、ftp等。在golang中,可通过使用第三方库,如net/http来进行网页下载。
网页解析器(parser)网页解析器主要负责对下载下来的网页进行解析,获取需要的数据并保存。golang中,可通过正则表达式、html5解析器、goquery等方法进行网页解析。
存储器(storage)存储器主要负责将已经解析下来的数据进行存储,一般有数据库存储和本地文件存储两种方式。golang中可以使用第三方库如gorm、orm等进行数据存储。
二、golang爬虫的编写方法
创建url管理器url管理器主要用来管理待爬取/已爬取的url,提供添加url、获取url、判断url是否存在等操作。
type urlmanager struct {    urls map[string]bool}// 新建url管理器func newurlmanager() *urlmanager {    return &urlmanager{urls: make(map[string]bool)}}// 添加url到管理器队列func (um *urlmanager) addurl(url string) bool {    if um.urls[url] {        // url已经存在        return false    }    um.urls[url] = true    return true}// 添加url列表到管理器队列func (um *urlmanager) addurls(urls []string) bool {    added := false    for _, url := range urls {        if um.addurl(url) {            added = true        }    }    return added}// 判断url是否存在func (um *urlmanager) hasurl(url string) bool {    return um.urls[url]}// 获取待爬取的urlfunc (um *urlmanager) geturl() string {    for url := range um.urls {        delete(um.urls, url)        return url    }    return }// 获取url数量func (um *urlmanager) urlcount() int {    return len(um.urls)}
创建网页下载器网页下载器主要用来下载指定的url对应的网页内容,并将其返回。
type downloader struct {    client *http.client}// 新建网页下载器func newdownloader() *downloader {    return &downloader{client: &http.client{}}}// 网页下载func (d *downloader) download(url string) ([]byte, error) {    req, err := http.newrequest(get, url, nil)    req.header.set(user-agent, mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/58.0.3029.110 safari/537.36)    resp, err := d.client.do(req)    if err != nil {        return nil, err    }    defer resp.body.close()    // 读取响应正文内容    contents, err := ioutil.readall(resp.body)    if err != nil {        return nil, err    }    return contents, nil}
创建网页解析器网页解析器主要用来解析下载下来的网页内容,并提取需要的数据。下面是以goquery为例的解析器示例:
type parser struct{}// 新建网页解析器func newparser() *parser {    return &parser{}}// 网页解析func (parser *parser) parse(content []byte) []string {    doc, err := goquery.newdocumentfromreader(bytes.newreader(content))    if err != nil {        log.fatal(err)    }    var urls []string    doc.find(a).each(func(i int, s *goquery.selection) {        href, exists := s.attr(href)        if exists && !strings.hasprefix(href, javascript) && len(href) > 1 {            // 绝对路径和相对路径都考虑            u, err := url.parse(href)            if err != nil {                return            }            if u.isabs() {                urls = append(urls, href)                return            }            // 补全相对路径,例如:./abc --> http://example.com/abc            base, _ := url.parse(contenturl)            urls = append(urls, base.resolvereference(u).string())        }    })    return urls}
创建存储器存储器主要用来将解析后的数据存储到本地或数据库中,此处以mysql数据库为例:
type storage struct {    db *gorm.db}//新建数据存储器func newstorage() *storage{    db, _ := gorm.open(mysql, root:password@tcp(localhost:3306)/mydb?charset=utf8&parsetime=true&loc=local)    return &storage{db:db}}// 保存数据到数据库func (storage *storage) savedata(data []string) {    for _, item := range data {        storage.db.create(&mymodel{name: item})    }}
爬虫控制器爬虫控制器主要实现爬虫的调度与协调功能。其主要流程为:
初始化url管理器、网页下载器、网页解析器、存储器;将待爬取的url添加到url管理器队列中;循环获取待爬取的url;判断url是否已被爬取过,若已爬取过,则跳过该url;下载url对应的网页;解析网页,并取出数据;将数据存储到数据库中;将url添加到已爬取的url列表中。func run() {    // 初始化url管理器、网页下载器、网页解析器、存储器    urlmanager := newurlmanager()    downloader := newdownloader()    parser := newparser()    storage := newstorage()    // 添加待爬取的url    urlmanager.addurl(http://example.com)    // 爬虫运行    for urlmanager.urlcount() > 0 {        // 获取待爬取的url        url := urlmanager.geturl()        // 判断url是否已爬取过        if downloader.iscrawled(url) {            continue        }        // 下载网页        contents, err := downloader.download(url)        if err != nil {            continue        }        // 解析网页        urls := parser.parse(contents)        // 存储数据        storage.savedata(urls)        // 将url添加到已爬取过的url列表        downloader.addcrawled(url)        // 将解析出来的url添加到url队列中        urlmanager.addurls(urls)    }}
完整代码package mainimport (    bytes    github.com/puerkitobio/goquery    github.com/jinzhu/gorm    _ github.com/jinzhu/gorm/dialects/mysql    io/ioutil    log    net/http    net/url    strings)type urlmanager struct {    urls map[string]bool}// 新建url管理器func newurlmanager() *urlmanager {    return &urlmanager{urls: make(map[string]bool)}}// 添加url到管理器队列// 添加url到管理器队列func (um *urlmanager) addurl(url string) bool {    if um.urls[url] {        // url已经存在        return false    }    um.urls[url] = true    return true}// 添加url列表到管理器队列func (um *urlmanager) addurls(urls []string) bool {    added := false    for _, url := range urls {        if um.addurl(url) {            added = true        }    }    return added}// 判断url是否存在func (um *urlmanager) hasurl(url string) bool {    return um.urls[url]}// 获取待爬取的urlfunc (um *urlmanager) geturl() string {    for url := range um.urls {        delete(um.urls, url)        return url    }    return }// 获取url数量func (um *urlmanager) urlcount() int {    return len(um.urls)}type downloader struct {    client *http.client    crawledurls map[string]bool}// 新建网页下载器func newdownloader() *downloader {    return &downloader{client: &http.client{}, crawledurls: make(map[string]bool)}}// 网页下载func (d *downloader) download(url string) ([]byte, error) {    req, err := http.newrequest(get, url, nil)    req.header.set(user-agent, mozilla/5.0 (windows nt 10.0; win64; x64) applewebkit/537.36 (khtml, like gecko) chrome/58.0.3029.110 safari/537.36)    resp, err := d.client.do(req)    if err != nil {        return nil, err    }    defer resp.body.close()    // 读取响应正文内容    contents, err := ioutil.readall(resp.body)    if err != nil {        return nil, err    }    return contents, nil}// 判断url是否已爬取func (d *downloader) iscrawled(url string) bool {    return d.crawledurls[url]}// 将url添加到已爬取列表中func (d *downloader) addcrawled(url string) {    d.crawledurls[url] = true}type parser struct{}// 新建网页解析器func newparser() *parser {    return &parser{}}// 网页解析func (parser *parser) parse(content []byte,contenturl string) []string {    doc, err := goquery.newdocumentfromreader(bytes.newreader(content))    if err != nil {        log.fatal(err)    }    var urls []string    doc.find(a).each(func(i int, s *goquery.selection) {        href, exists := s.attr(href)        if exists && !strings.hasprefix(href, javascript) && len(href) > 1 {            // 绝对路径和相对路径都考虑            u, err := url.parse(href)            if err != nil {                return            }            if u.isabs() {                urls = append(urls, href)                return            }            // 补全相对路径            base, _ := url.parse(contenturl)            urls = append(urls, base.resolvereference(u).string())        }    })    return urls}type mymodel struct {    gorm.model    name string}type storage struct {    db *gorm.db}//新建数据存储器func newstorage() *storage{    db, _ := gorm.open(mysql, root:password@tcp(localhost:3306)/mydb?charset=utf8&parsetime=true&loc=local)    db.automigrate(&mymodel{})    return &storage{db:db}}// 保存数据到数据库func (storage *storage) savedata(data []string) {    for _, item := range data {        storage.db.create(&mymodel{name: item})    }}func run() {    // 初始化url管理器、网页下载器、网页解析器、存储器    urlmanager := newurlmanager()    downloader := newdownloader()    parser := newparser()    storage := newstorage()    // 添加待爬取的url    urlmanager.addurl(http://example.com)    // 爬虫运行    for urlmanager.urlcount() > 0 {        // 获取待爬取的url        url := urlmanager.geturl()        // 判断url是否已爬取过        if downloader.iscrawled(url) {            continue        }        // 下载网页        contents, err := downloader.download(url)        if err != nil {            continue        }        // 解析网页        urls := parser.parse(contents,url)        // 存储数据        storage.savedata(urls)        // 将url添加到已爬取过的url列表        downloader.addcrawled(url)        // 将解析出来的url添加到url队列中        urlmanager.addurls(urls)    }}func main(){    run()}
三、总结
golang爬虫具有简洁、高效和可扩展性的特点,并且由于其天然的并发优势,可以大大提高爬取数据速度。本文通过介绍golang爬虫的基本组成和编写方法,希望能够对读者有所帮助,也欢迎读者们在实践中积累更多的经验。
以上就是golang爬虫的基本组成部分和编写方法的详细内容。
该用户其它信息

VIP推荐

免费发布信息,免费发布B2B信息网站平台 - 三六零分类信息网 沪ICP备09012988号-2
企业名录 Product