数据抓取之性能优化第一弹

数据抓取本身流程很简单,但是当遇到网站的种类变多或者要采集的数据变多的时候,性能问题会称为数据抓取中要首要解决的问题。
这几天同事在测试采集数据的时候总是遇到反应很慢的情况。今晚趁着洗完澡脑子清醒,针对部分问题重构了下;做下记录。

这次遇到的问题主要是代理的问题,场景是这样的:

  • 我有100个代理,
  • 系统初始化的时候,我把这100个代理中放到一个队列(ArrayBlockingQueue)中。
  • 然后平均每个采集类(一个采集类对应一个网站或者一类网站)分配10个代理。
  • 问题来了,当我网站超过10个到11个的时候,这时候启动系统,第十一个采集类会无法从代理中获取代理。于是第十一个类一直在登真队列中哪个好心人把代理资源放回来。可惜它永远登不到那天。

问题的原因其实是我多虑了,因为代理资源本身是可以多个采集类共用的。而我起初的考虑是为了让代理资源能够均衡使用,不至于某个代理频繁的被使用,而某些代理永远没有用到(浪费了)。

我的解决方法是这样的:

  • 把代理资源放在一个List中,而不是队列中。
  • 每个采集类获取代理的时候从list中顺序获取,从第1个代理获取,到100个以后,再重头开始继续依次获取。
  • 由于List中无法自己标记当前获取到第几个了,且在多线程环境下,所以使用了AtomicInteger来做计数器。
  • 参考代码如下:
    import java.io.InputStream;
    import java.util.List; 
    import java.util.concurrent.atomic.AtomicInteger;

    import org.apache.commons.io.IOUtils;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;


    public class ProxieQueue {

        private static Logger logger = LoggerFactory.getLogger(ProxieQueue.class);
        private static List<Proxie> proxieList = com.google.common.collect.Lists.newArrayList();
        private static AtomicInteger listCounter =new AtomicInteger();
        private ProxieQueue() {

        }

        static {
            try {
                InputStream is =Configurations.class.getClassLoader().getResourceAsStream("proxies.txt");
                List<String> lineList = IOUtils.readLines(is); ;
                for (String line : lineList) {
                    String[] strArray = line.split(":");

                    Proxie proxie = new Proxie();
                    proxie.setUrl(strArray[0]);
                    proxie.setUser(strArray[1]);
                    proxie.setPass(strArray[2]);
                    proxie.setPort(Integer.valueOf(strArray[3]));
                    proxieList.add(p);
                }
            } catch (Exception e) {
                logger.error("读取代理配置失败", e);
            }


        }


        public static Proxie get() {
            int index = listCounter.getAndIncrement();
                if(index == proxieList.size()){
                   //获取到结尾后,从头开始继续获取
                   index= listCounter.getAndSet(0);
                }
                return  proxieList.get(index);       
        }
    }
  • 另外我是在系统初始化的时候就将各个网站的采集类初始化好的,这样其实没有必要,完全可以在采集这个网站的时候再进行初始化即可。

欢迎去我的个人站点查看文章
或者,欢迎关注俺的微信订阅号,每天一篇小笔记,每天提高一点点:

公众号:enilu123
这里写图片描述

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值