注:对代码及思路进行了改进—Java网络爬虫(十一)–重构定时爬取以及IP代理池(多线程+Redis+代码优化)


定点爬取

当我们需要对金融行业的股票信息进行爬取的时候,由于股票的价格是一直在变化的,我们不可能手动的去每天定时定点的运行程序,这个时候我们就需要实现定点爬取了,我们引入第三方库quartz的使用:

package timeutils;import org.quartz.CronTrigger;
import org.quartz.JobDetail;
import org.quartz.Scheduler;
import org.quartz.SchedulerFactory;
import org.quartz.impl.StdSchedulerFactory;import java.text.SimpleDateFormat;
import java.util.Date;import static org.quartz.CronScheduleBuilder.cronSchedule;
import static org.quartz.JobBuilder.newJob;
import static org.quartz.TriggerBuilder.newTrigger;/*** Created by paranoid on 17-4-13.*/public class TimeUpdate {public void go() throws Exception {// 首先,必需要取得一个Scheduler的引用(设置一个工厂)SchedulerFactory sf = new StdSchedulerFactory();//从工厂里面拿到一个scheduler实例Scheduler sched = sf.getScheduler();//真正执行的任务并不是Job接口的实例,而是用反射的方式实例化的一个JobDetail实例JobDetail job = newJob(MyTimeJob.class).withIdentity("job1", "group1").build();// 定义一个触发器,job 1将每隔执行一次CronTrigger trigger = newTrigger().withIdentity("trigger1", "group1").withSchedule(cronSchedule("50 47 17 * * ?")).build();//执行任务和触发器Date ft = sched.scheduleJob(job, trigger);//格式化日期显示格式SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss SSS");System.out.println(job.getKey() + " 已被安排执行于: " + sdf.format(ft) + "," +"并且以如下重复规则重复执行: " + trigger.getCronExpression());sched.start();}public static void main(String[] args) throws Exception {TimeUpdate test = new TimeUpdate();test.go();}
}

在上面的代码中,已经详细的给出了实现定时爬取的基本代码:

JobDetail job = newJob(MyTimeJob.class).withIdentity("job1", "group1").build();

这句代码中的MyTimeJob.class就是我们要执行的任务代码,它是通过类的反射加载机制进行运行的,之后我们设置它为第一组的第一个任务。

要使用这个第三方库我们需要了解一些cron表达式的概念,网上由于对它的说明很多,我就不再这里进行说明 ,大家可以看到:

cronSchedule("50 47 17 * * ?")

我设置的是每天的17:47:50秒运行这个程序。

值得注意的是:我们所要执行的任务必须写在execute方法之中,在下面的代码就是一个实例,也就是我们需要实现的IP代理池。


IP代理池

在网上搜索了很多关于反爬虫的机制,实用的还是IP代理池,我依照网上的思想自己写了一个,大致的思路是这样的:

  1. 首先我使用本机IP在xici(西刺)代理网站上的高匿IP代理区抓取了第一页的代理IP放入了一个数组之中;
  2. 然后我使用数组中的IP对要访问的页面进行轮番调用,每访问一个页面就换一个IP;
  3. 我将得到的IP按链接速度的快慢进行排序,选需速度最快的前100个;
  4. 我对得到的IP进行测试,如果不能使用就在容器中删除;
  5. 将最终的IP写入数据库中。

实现IP代理池的主要逻辑代码如下:

package timeutils;import IPModel.DatabaseMessage;
import IPModel.IPMessage;
import database.DataBaseDemo;
import htmlparse.URLFecter;
import ipfilter.IPFilter;
import ipfilter.IPUtils;
import org.quartz.Job;
import org.quartz.JobExecutionContext;
import org.quartz.JobExecutionException;import java.io.IOException;
import java.util.ArrayList;
import java.util.List;import static java.lang.System.out;/*** Created by paranoid on 17-4-13.*/public class MyTimeJob implements Job {public void execute(JobExecutionContext argv) throws JobExecutionException {List<String> Urls = new ArrayList<>();List<DatabaseMessage> databaseMessages = new ArrayList<>();List<IPMessage> list = new ArrayList<>();List<IPMessage> ipMessages = new ArrayList<>();String url = "http://www.xicidaili.com/nn/1";String IPAddress;String IPPort;int k, j;//首先使用本机ip进行爬取try {list = URLFecter.urlParse(url, list);} catch (IOException e) {e.printStackTrace();} catch (ClassNotFoundException e) {e.printStackTrace();}//对得到的IP进行筛选,选取链接速度前100名的list = IPFilter.Filter(list);//构造种子Urlfor (int i = 1; i <= 5; i++) {Urls.add("http://www.xicidaili.com/nn/" + i);}//得到所需要的数据for (k = 0, j = 0; j < Urls.size(); k++) {url = Urls.get(j);IPAddress = list.get(k).getIPAddress();IPPort = list.get(k).getIPPort();//每次爬取前的大小int preIPMessSize = ipMessages.size();try {ipMessages = URLFecter.urlParse(url, IPAddress, IPPort, ipMessages);//每次爬取后的大小int lastIPMessSize = ipMessages.size();if(preIPMessSize != lastIPMessSize){j++;}//对IP进行轮寻调用if (k >= list.size()) {k = 0;}} catch (ClassNotFoundException e) {e.printStackTrace();} catch (IOException e) {e.printStackTrace();}}//对得到的IP进行筛选,选取链接速度前100名的ipMessages = IPFilter.Filter(ipMessages);//对ip进行测试,不可用的从数组中删除ipMessages = IPUtils.IPIsable(ipMessages);for(IPMessage ipMessage : ipMessages){out.println(ipMessage.getIPAddress());out.println(ipMessage.getIPPort());out.println(ipMessage.getServerAddress());out.println(ipMessage.getIPType());out.println(ipMessage.getIPSpeed());}//将得到的IP存储在数据库中(每次先清空数据库)try {DataBaseDemo.delete();DataBaseDemo.add(ipMessages);} catch (ClassNotFoundException e) {e.printStackTrace();}//从数据库中将IP取到try {databaseMessages = DataBaseDemo.query();} catch (ClassNotFoundException e) {e.printStackTrace();}for (DatabaseMessage databaseMessage: databaseMessages) {out.println(databaseMessage.getId());out.println(databaseMessage.getIPAddress());out.println(databaseMessage.getIPPort());out.println(databaseMessage.getServerAddress());out.println(databaseMessage.getIPType());out.println(databaseMessage.getIPSpeed());}}
}

整个IP代理池程序的实现架构如下:

  1. database包中包装了数据库的各种操作;
  2. htmlparse包中主要实现了对得到的html页面的解析工作;
  3. httpbrowser包中主要实现了返回请求Url返回html页面的工作;
  4. ipfilter包中主要实现了IP的过滤(速度可好)和检测(是否可用);
  5. ipmodel中主要封装了抓取ip的维度和从数据库中拿到的ip的维度;
  6. timeutils主要实现了定点爬取和整体逻辑。

源码链接

有兴趣的同学可以前往我的github上查看整个项目的源码,代码量不多而且注释也比较清晰,如果觉得不错的话可以给个星哦~~

实现定时爬取与IP代理池

Java网络爬虫(七)--实现定时爬取与IP代理池相关推荐

  1. Java网络爬虫(三)爬取网络小说

    因CSDN版权问题,小说网站的URL.图片不可在此公布,读者根据自己想要爬取的网站,自行选择网站即可. 1.爬取小说章节内容,需要注意的大部分原创小说内容页是禁用右键的,无法直接选取页面内容进行元素检 ...

  2. python通过ip池爬_python爬虫18 | 就算你被封了也能继续爬,使用IP代理池伪装你的IP地址,让IP飘一会...

    我们上次说了伪装头部 ↓ 让自己的 python 爬虫假装是浏览器 小帅b主要是想让你知道 在爬取网站的时候 要多的站在对方的角度想问题 其实 这和泡妞差不多 你要多站在妹纸的角度思考 她的兴趣是什么 ...

  3. 网络爬虫:使用多线程爬取网页链接

    前言: 经过前面两篇文章,你想大家应该已经知道网络爬虫是怎么一回事了.这篇文章会在之前做过的事情上做一些改进,以及说明之前的做法的不足之处. 思路分析: 1.逻辑结构图 上图中展示的就是我们网络爬虫中 ...

  4. Python网络爬虫requests、bs4爬取空姐图片,福利哦

    Scrapy框架很好,也提供了很多扩展点,可以自己编写中间件处理Scrapy的Request和Response.但是可定制化或者可掌控性来说,还是自己写的爬虫更加强一些. 接下来,我们来看一下使用Py ...

  5. python网络爬虫实战——利用逆向工程爬取动态网页

    前言 之前写过介绍过网络爬虫的文章,都是一些基础知识,所以在接下来我们完成一个小任务--利用逆向工程爬取一个动态网页,360壁纸网站(https://image.so.com/z?ch=wallpap ...

  6. Python网络爬虫:利用正则表达式爬取豆瓣电影top250排行前10页电影信息

    在学习了几个常用的爬取包方法后,转入爬取实战. 爬取豆瓣电影早已是练习爬取的常用方式了,网上各种代码也已经很多了,我可能现在还在做这个都太土了,不过没事,毕竟我也才刚入门-- 这次我还是利用正则表达式 ...

  7. 网络爬虫(动态网页爬取关于混合动力汽车的论文数据)

    一.实验目的 (1) 熟悉网页浏览器开发工具的使用: (2) 掌握动态网页加载过程: (3) 掌握 post 请求参数设置: (4) 掌握基本的反反爬技术: (5) 能够根据问题需求,指定网络爬虫方案 ...

  8. 网络爬虫---用urllib模块爬取京东笔记本电脑的数据、并对其做一个可视化

    用urllib模块爬取京东笔记本电脑的数据.并对其做一个可视化 文章目录 用urllib模块爬取京东笔记本电脑的数据.并对其做一个可视化 一.前言 二.知识要求 三.过程分析 1.观察主页面和每个电脑 ...

  9. 【爬虫】每天定时爬取网页小故事并发送至指定邮箱

    看题目 ,需要实现三部分工作,第一部分为爬取网页小故事,第二部分为发送至指定邮箱,第三部分为定时启动程序.爬取网页内容可以使用BeautifulSoup库实现,发送邮件可以使用smtplib库实现,定 ...

  10. Python网络爬虫(6)--爬取淘宝模特图片

    经过前面的一些基础学习,我们大致知道了如何爬取并解析一个网页中的信息,这里我们来做一个更有意思的事情,爬取MM图片并保存.网址为https://mm.taobao.com/json/request_t ...

最新文章

  1. Xshell 配置是vi显示多种颜色
  2. 富文本编辑_博客的后台富文本编辑和阅读计数
  3. yolov5 tensorrt
  4. c++ 字符类型总结区别wchar_t,char,WCHAR(转)
  5. HTML DOM - 修改 HTML 内容
  6. 计算机英语作文句子,英语作文经典句子
  7. 最短路径和距离及可视化——matlab
  8. 饿了么前端DEMO 网址 VUE.js
  9. android开发 视图联动_Flutter混合APP开发
  10. Excel2013数据透视表、Power View中的钻取
  11. visio作图的一系列坑
  12. 管螺纹如何标注_螺纹知识,这一次搞全了!
  13. Error: ENOENT: no such file or directory, scandir .....
  14. Matla + SVD 求解变换矩阵
  15. 【低碳发展案例研究】中国西部中小城市低碳发展研究——以泸州市为例
  16. 在mysql中更新数据sql语句怎么写_在MySQL中,更新数据库表记录的SQL语句,包括______语句...
  17. 《红楼梦》之金陵十二钗vs韩国明星
  18. 【信息安全案例】——网络信息面临的安全威胁(学习笔记)
  19. 【AWS+Drupal应用案例】如何让一个千万级流量网站从一直挂机到起死回生?
  20. Scanner的基本用法

热门文章

  1. Android 原生插件开发步骤
  2. 金盾播放器android安卓,金盾高级视频加密系统跨平台播放器Android安卓安装步骤.doc...
  3. 24小时“凶宅试睡直播”去“凶”,阿里拍卖为卖凶宅有点拼
  4. 协调器掉线,路由和终端节点的不同表现
  5. 或是独体字吗_独体字
  6. 手把手教你微信公众号如何给指定用户发送消息提醒
  7. Windows更改鼠标滚轮的滚动速度(系统各个软件中上下翻页的速度)
  8. 大数据平台核心架构图鉴,建议收藏!
  9. (连载0.1)实践报告:在深度系统用Python3对上市公司年度报告财务报表进行提取
  10. 写在博士旅程之前|博士第一年|博士第三年|博士第四年