首先讲下这个项目的功能,及所用到的技术,
1:因怕爬去网页时ip被封,所以用到了代理ip接口,这个接口每请求一次会返回十个ip,及对应端口号 将其split后add进list
2:有了代理ip,下面就可以对网页放心的操作了,但是这时问题来了,并不是所有的代理ip都能用,一旦碰到无用ip就重新请求就太浪费资源,而list直接掉无用的元素,再到下一次for循环中就会报错
通俗的讲就是list 不允许在遍历的同时他的元素 网上找的说法是:
API中此异常的解释:当方法检测到对象的并发修改,但不允许这种修改时,抛出此异常 。原因:Iterator 是工作在一个独立的线程中,并且拥有一个 mutex 锁 。Iterator 被创建之后会建立一个指向原来对象的单链索引表,当原来的对象数量发生变化时,这个索引表的内容不会同步改变,所以当索引指针往后移动的时候就找不到要迭代的对象,所以按照 fail-fast 原则 Iterator 会马上抛出 Java.util.ConcurrentModificationException 异常 。所以 Iterator 在工作的时候是不允许被迭代的对象被改变的 。但你可以使用 Iterator 本身的方法 remove() 来删除对象,Iterator.remove() 方法会在删除当前迭代对象的同时维护索引的一致性 。
个人的理解是操作的元素销毁了,但是指向这个元素的索引还在,所以再便利时找不到元素就会报错 。
解决方案也是在网上找的例子,用迭代器对list中的元素进行操作
Iterator iterator = daiLiIp.iterator();while (iterator.hasNext()) {String[] ss = iterator.next();String ip = ss[0];String num = ss[1];int port = 0;try {port = Integer.parseInt(num);} catch (NumberFormatException e) {log.debug("GetSoundCodeUtil类:"+e.getMessage());}String connectState = getSoundCode(ip, port, url, codingFormat);// 连接状态只有为false时是连接失败if ("false".equals(connectState)) {daiLiIp.remove(ss); // 移除list中无用ipiterator = null;// 重新置空迭代器System.gc();// 垃圾回收iterator = daiLiIp.iterator();// 迭代器重新赋值if (daiLiIp.size() == 0) {// 如果代理ip集合为0就重新调接口daiLiIp = GetDaiLiIpUtil.getDaiLiIp();iterator = daiLiIp.iterator();}continue;// 进入下次循环} else {return connectState;// 停止循环}}return null;
3:对网页的爬取:
文章插图
(1):只爬取页面上的数据 用 简历连接拿到网页源码
【简单爬虫项目总结_01】
//创建HttpClient对象HttpClient http = new DefaultHttpClient();//设置相应时间,设置获取源码时间,设置代理服务器http.getParams().setParameter(CoreConnectionPNames.CONNECTION_TIMEOUT,100000)//连接超时 指的是连接一个url的连接等待时间.setParameter(CoreConnectionPNames.SO_TIMEOUT, 100000)//等待客户连接的超时时间.setParameter(ConnRouteParams.DEFAULT_PROXY, new HttpHost("ip",端口号));//创建请求对象,get还是post看情况HttpGet hGet = new HttpGet("http://js.avis.cn/sources/cityshopsdata.js?version=20170301162501");HttpResponse response = http.execute(hGet);//EntityUtils工具类把网页实体转换成字符串String str = EntityUtils.toString(response.getEntity(),"utf-8");
//拿到网页源码再对其进行解析
Elements code = GetElementsUtil.getElements(网页源码,"要拿到的标签交id或class(ul.titles.l)");for (Element entityCode : code) {//可以继续对拿到的标签进行解析}
(2)爬取到json字符串数据:
如果需要带信息才能拿到数据可以在向父网站发送请求时
- 一 构建SpringCloud 项目初始环境
- 最简单的 UE 4 C++ 教程 —— Actor 线轨迹(line trace
- pdf怎么转换成图片?用这几种简单方法搞定
- QT QT KIT简单介绍
- 【Python爬虫】CSDN热榜文章热门词汇分析
- RSA加解密简单实现
- Koa学习1:初始化项目
- python:爬虫-selenium,BeautifulSoup,urllib
- 公众号项目总结
- C语言项目实战:《连连看》基础项目丨460 行源码注释