设为首页 加入收藏

TOP

用golang 实现一个代理池(一)
2018-10-19 15:52:51 】 浏览:422
Tags:golang 实现 一个 代理

背景

写爬虫的时候总会遇到爬取速度过快而被封IP的情况,这个时候就需要使用代理了。在https://github.com/henson/ProxyPool
的启发下,决定自己实现一个代理池。项目已经开源在github。

https://github.com/AceDarkknight/GoProxyCollector

2018.03.29更新

  • go 版本升级为1.9.4,使用新版本的sync.Map 提高并发读的效率

开发环境

windows 7,Go 1.8.4

数据来源

http://www.xicidaili.com
http://www.89ip.cn
http://www.kxdaili.com/
https://www.kuaidaili.com
http://www.ip3366.net/
http://www.ip181.com/
http://www.data5u.com
https://proxy.coderbusy.com

项目结构

目录 作用
collector 收集器,抓取各个网站的代理
result 表示抓取的结果
scheduler 负责任务调度,包括启动collector和入库
server 启动一个web服务,提供取结果的API
storage 存储结果,通过接口可以使用别的数据库
util 一些常用的工具方法
verifier ip的验证与入库出库

实现

  • collector
    collector 支持两种模式,分别是使用goquery对网页元素进行选择和使用正则表达式匹配我们需要的信息。直接上代码吧。
// github.com\AceDarkknight\GoProxyCollector\collector\selectorCollector.go
func (c *SelectorCollector) Collect(ch chan<- *result.Result) {
    // 退出前关闭channel。
    defer close(ch)

    response, _, errs := gorequest.New().Get(c.currentUrl).Set("User-Agent", util.RandomUA()).End()
    
    /* 省略部分代码 */

    // 有些网站不是UTF-8编码的,需要进行转码。
    var decoder mahonia.Decoder
    if c.configuration.Charset != "utf-8" {
        decoder = mahonia.NewDecoder(c.configuration.Charset)
    }

    // 使用goquery。
    doc, err := goquery.NewDocumentFromReader(response.Body)
    if err != nil {
        seelog.Errorf("parse %s error:%v", c.currentUrl, err)
        return
    }

    // 大部分代理网站的代理列表都放在一个table里,先选出table再循环里面的元素。
    selection := doc.Find(c.selectorMap["table"][0])
    selection.Each(func(i int, sel *goquery.Selection) {
        var (
            ip       string
            port     int
            speed    float64
            location string
        )

        // 我们需要的信息的名字和路径存在collectorConfig.xml。
        nameva lue := make(map[string]string)
        for key, value := range c.selectorMap {
            if key != "table" {
                var temp string
                if len(value) == 1 {
                    temp = sel.Find(value[0]).Text()
                } else if len(value) == 2 {
                    temp, _ = sel.Find(value[0]).Attr(value[1])
                }

                // 转码.
                if temp != "" {
                    if decoder != nil {
                        temp = decoder.ConvertString(temp)
                    }

                    nameva lue[key] = temp
                }
            }
        }

        /* 省略部分代码 */

        // 过滤一些不符合条件的结果
        if ip != "" && port > 0 && speed >= 0 && speed < 3 {
            r := &result.Result{
                Ip:       ip,
                Port:     port,
                Location: location,
                Speed:    speed,
                Source:   c.currentUrl}

            // 把符合条件的结果放进channel
            ch <- r
        }
    })
}

// github.com\AceDarkknight\GoProxyCollector\collector\regexCollector.go
func (c *RegexCollector) Collect(ch chan<- *result.Result) {
    response, bodyString, errs := gorequest.New().Get(c.currentUrl).Set("User-Agent", util.RandomUA()).End()
    
    /* 省略部分代码 */

    // 用正则匹配。
    regex := regexp.MustCompile(c.selectorMap["ip"])
    ipAddresses := regex.FindAllString(bodyString, -1)
    if len(ipAddresses) <= 0 {
        seelog.Errorf("can not found correct format ip address in url:%s", c.currentUrl)
        return
    }

    for _, ipAddress := range ipAddresses {
        temp := strings.Split(ipAddress, ":")
        if len(temp) == 2 {
            port, _ := strconv.Atoi(temp[1])
            if port <= 0 {
                continue
            }

            r := &result.Result{
                Ip:     temp[0],
                Port:   port,
                Source: c.currentUrl,
            }

            ch <- r
        }
    }
}
  • result
    result很简单,只是用来表示collector爬取的结果。
// github.com\AceDarkknight\GoProxyCollector\result\result.go
type Result struct {
    Ip       string  `json:"ip"`
    Port     int     `json:"port"`
    Location stri
首页 上一页 1 2 3 下一页 尾页 1/3/3
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇go语言defer panic recover用法总.. 下一篇go语言的数组和切片区别

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目