笔记-网络爬虫实现java

目录:
1、爬虫原理
2、本地文件数据提取及分析

3、单网页数据的读取

4、运用正则表达式完成超连接的连接匹配和提取

5、广度优先遍历,多网页的数据爬取

6、多线程的网页爬取

7、总结
爬虫实现原理
网络爬虫基本技术处理

网络爬虫是数据采集的一种方法,实际项目开发中,通过爬虫做数据采集一般只有以下几种情况:

1) 搜索引擎

2) 竞品调研

3) 舆情监控

4) 市场分析

网络爬虫的整体执行流程:

1) 确定一个(多个)种子网页

2) 进行数据的内容提取

3) 将网页中的关联网页连接提取出来

4) 将尚未爬取的关联网页内容放到一个队列中

5) 从队列中取出一个待爬取的页面,判断之前是否爬过。

6) 把没有爬过的进行爬取,并进行之前的重复操作。

7) 直到队列中没有新的内容,爬虫执行结束。

这样完成爬虫时,会有一些概念必须知道的:

1) 深度(depth):一般来说,表示从种子页到当前页的打开连接数,一般建议不要超过5层。

2) 广度(宽度)优先和深度优先:表示爬取时的优先级。建议使用广度优先,按深度的层级来顺序爬取。

Ⅰ  在进行网页爬虫前,我们先针对一个飞机事故失事的文档进行数据提取的练习,主要是温习一下上一篇的java知识,也是为了下面爬虫实现作一个热身准备。

首先分析这个文档,,关于美国历来每次飞机失事的数据,包含时间地点、驾驶员、死亡人数、总人数、事件描述,一共有12列,第一列是标题,下面一共有5268条数据。

现在我要对这个文件进行数据提取,并实现一下分析:

根据飞机事故的数据文档来进行简单数据统计。

1) 哪年出事故次数最多

2) 哪个时间段(上午 8 – 12,下午 12 – 18,晚上 18 – 24,凌晨 0 – 8 )事故出现次数最多。

3) 哪年死亡人数最多

4)哪条数据的幸存率最高。

代码实现:(一切知识从源码获取!)

 1 package com.plane;
  2 
  3 import java.io.*;
  4 import java.text.ParseException;
  5 import java.text.SimpleDateFormat;
  6 import java.util.*;
  7 /**
  8  * 飞机事故统计
  9  * @author k04
 10  *sunwengang    
 11  *2017-08-11
 12  */
 13 public class planeaccident {
 14         //数据获取存取链表
 15         private static List<String>  alldata=new ArrayList<>();
 16         
 17         public static void main(String args[]){            
 18             getData("飞行事故数据统计_Since_1908.csv");
 19             alldata.remove(0);
 20             //System.out.println(alldata.size());
 21             //死亡人数最多的年份
 22             MaxDeadYear();
 23             //事故发生次数最多的年份
 24             MaxAccidentsYear();
 25             //事故各个时间段发生的次数
 26             FrequencyPeriod();
 27             //幸村率最高的一条数据
 28              MaximumSurvival();        
 29         }
 30         
 31         /**
 32          * 从源文件爬取数据
 33          * getData(String filepath)
 34          * @param filepath
 35          */
 36         public static void getData(String filepath){
 37             File f=new File(filepath);
 38             //行读取数据
 39             try{
 40                 BufferedReader br=new BufferedReader(new FileReader(f));
 41                 String line=null;
 42                 while((line=(br.readLine()))!=null){
 43                     alldata.add(line);
 44                 }
 45                 br.close();
 46             }catch(Exception e){
 47                 e.printStackTrace();
 48             }
 49         }
 50         /**
 51          * 记录每年对应的死亡人数
 52          * @throws  
 53          * 并输出死亡人数最多的年份,及该年死亡人数
 54          */
 55         public static void MaxDeadYear(){
 56             //记录年份对应死亡人数
 57             Map<Integer,Integer> map=new HashMap<>();
 58             //时间用date显示
 59             SimpleDateFormat sdf=new SimpleDateFormat("MM/dd/YYYY");
 60             //循环所有数据
 61             for(String data:alldata){
 62                 //用逗号将数据分离,第一个是年份,第11个是死亡人数
 63                 String[] strs=data.split(",");
 64                 if(strs[0]!=null){
 65                     //获取年份
 66                     try {
 67                         Date date=sdf.parse(strs[0]);
 68                         int year=date.getYear();
 69                         //判断map中是否记录过这个数据
 70                         if(map.containsKey(year)){
 71                             //已存在,则记录数+该年死亡人数
 72                             map.put(year, map.get(year)+Integer.parseInt(strs[10]));
 73                         }else{
 74                             map.put(year, Integer.parseInt(strs[10]));
 75                         }
 76                         
 77                     } catch (Exception e) {
 78                         // TODO Auto-generated catch block
 79                         
 80                     }
 81                     
 82                 }
 83             }
 84             //System.out.println(map);
 85             
 86             //记录死亡人数最多的年份
 87             int max_year=-1;
 88             //记录死亡人数
 89             int dead_count=0;
 90             //用set无序获取map中的key值,即年份
 91             Set<Integer> keyset=map.keySet();
 92             //
 93             for(int year:keyset){
 94                 //当前年事故死亡最多的年份,记录年和次数
 95                 if(map.get(year)>dead_count&&map.get(year)<10000){
 96                     max_year=year;
 97                     dead_count=map.get(year);
 98                 }
 99             }
100             
101             System.out.println("死亡人数最多的年份:"+(max_year+1901)+"   死亡人数:"+dead_count);
102         }
103         /**
104          * 记录事故次数最多的年份
105          * 输出该年及事故次数
106          */
107         public static void MaxAccidentsYear(){
108             //存放年份,该年的事故次数
109             Map<Integer,Integer> map=new HashMap<>();
110             SimpleDateFormat sdf =new SimpleDateFormat("MM/dd/YYYY");
111             //循环所有数据
112             for(String data:alldata){
113                 String[] strs=data.split(",");
114                 if(strs[0]!=null){
115                     try {
116                         Date date=sdf.parse(strs[0]);
117                         //获取年份
118                         int year=date.getYear();
119                         //判断是否存在记录
120                         if(map.containsKey(year)){
121                             //已存在记录,+1
122                             map.put(year, map.get(year)+1);
123                         }else{
124                             map.put(year, 1);
125                         }
126                     } catch (Exception e) {
127                         // TODO Auto-generated catch block                        
128                     }                                                
129                 }
130             }
131             //记录事故次数最多的年份
132             int max_year=0;
133             //该年事故发生次数
134             int acc_count=0;
135             //循环所有数据,获取事故次数最多的年份
136             Set<Integer> keyset=map.keySet();
137             for(int year:keyset){
138                 if(map.get(year)>acc_count){
139                     max_year=year;
140                     acc_count=map.get(year);
141                 }
142             }
143             //输出结果
144             System.out.println("事故次数最多的年份"+(max_year+1901)+"  该年事故发生次数:"+acc_count);
145         }
146         /**
147          * FrequencyPeriod()
148          * 各个时间段发生事故的次数
149          */
150         public static void FrequencyPeriod(){
151             //key为时间段,value为发生事故次数
152             Map<String,Integer>  map=new HashMap<>();
153             //String数组存放时间段
154             String[] strsTime={"上午(6:00~12:00)","下午(12:00~18:00)","晚上(18:00~24:00)","凌晨(0:00~6:00)"};
155             //小时:分钟
156             SimpleDateFormat sdf=new SimpleDateFormat("HH:mm");
157             
158             for(String data:alldata){
159                 String[] strs=data.split(",");
160                 //判断时间是否记录,未记录则忽略
161                 if(strs[1]!=null){
162                     try {
163                         Date date=sdf.parse(strs[1]);
164                         //取得小时数
165                         int hour=date.getHours();
166                         //判断小时数在哪个范围中
167                         int index=0;
168                         if(hour>=12&&hour<18){
169                             index=1;
170                         }else if(hour>=18){
171                             index=2;
172                         }else if(hour<6){
173                             index=3;
174                         }
175                         //记录到map中
176                         if(map.containsKey(strsTime[index])){
177                             map.put(strsTime[index], map.get(strsTime[index])+1);
178                         }else{
179                             map.put(strsTime[index], 1);
180                         }                                                            
181                     } catch (ParseException e) {                        
182                     }                
183                 }
184                 
185             }
186             /*
187             System.out.println("各时间段发生事故次数:");
188             for(int i=0;i<strsTime.length;i++){        
189             System.out.println(strsTime[i]+" : "+map.get(strsTime[i]));
190             }        
191             */
192             // 记录出事故最多的时间范围
193             String maxTime = null;
194             // 记录出事故最多的次数
195             int maxCount = 0;
196 
197             Set<String> keySet = map.keySet();
198             for (String timeScope : keySet) {
199                 if (map.get(timeScope) > maxCount) {
200                     // 当前年就是出事故最多的年份,记录下年和次数
201                     maxTime = timeScope;
202                     maxCount = map.get(timeScope);
203                 }
204             }
205             System.out.println("发生事故次数最多的时间段:");
206             System.out.println(maxTime+" : "+maxCount);                            
207         }
208         /**
209          * 获取幸村率最高的一条数据的内容
210          * 返回该内容及幸存率
211          */
212         public static void MaximumSurvival(){
213             //存放事故信息以及该事故的幸村率
214             Map<String,Float> map=new HashMap<>();
215             //SimpleDateFormat sdf =new SimpleDateFormat("MM/dd/YYYY");
216             //事故幸存率=1-死亡率,第十一个是死亡人数,第十个是总人数
217             float survial=0;        
218             //循环所有数据
219             for(String data:alldata){
220                 try{
221                 String[] strs=data.split(",");
222                 //计算幸存率
223                 float m=Float.parseFloat(strs[10]);
224                 float n=Float.parseFloat(strs[9]);
225                 survial=1-m/n;
226                 map.put(data, survial);
227                 }catch(Exception e){
228                     
229                 }
230             }
231             //记录事故次数最多的年份
232             float max_survial=0;    
233             //幸存率最高的数据信息
234             String this_data="null";
235             //循环所有数据,获取事故次数最多的年份
236             Set<String> keyset=map.keySet();
237             for(String data:keyset){
238                 if(map.get(data)>max_survial){
239                     this_data=data;
240                     max_survial=map.get(data);
241                 }
242             }
243             System.out.println("幸存率最高的事故是:"+this_data);
244             System.out.println("幸存率为:"+survial);
245         }    
246 }

Ⅱ  接下来我们就可以在网页的数据上下手了。

下面先实现一个单网页数据提取的功能。

使用的技术可以有以下几类:

1) 原生代码实现:

a) URL类

2) 使用第三方的URL库

a) HttpClient库

3) 开源爬虫框架

a) Heritrix

b) Nutch

  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
爬虫(Web Crawler)是一种自动化程序,用于从互联网上收集信息。其主要功能是访问网页、提取数据并存储,以便后续分析或展示。爬虫通常由搜索引擎、数据挖掘工具、监测系统等应用于网络数据抓取的场景。 爬虫的工作流程包括以下几个关键步骤: URL收集: 爬虫从一个或多个初始URL开始,递归或迭代地发现新的URL,构建一个URL队列。这些URL可以通过链接分析、站点地图、搜索引擎等方式获取。 请求网页: 爬虫使用HTTP或其他协议向目标URL发起请求,获取网页的HTML内容。这通常通过HTTP请求库实现,如Python中的Requests库。 解析内容: 爬虫对获取的HTML进行解析,提取有用的信息。常用的解析工具有正则表达式、XPath、Beautiful Soup等。这些工具帮助爬虫定位和提取目标数据,如文本、图片、链接等。 数据存储: 爬虫将提取的数据存储到数据库、文件或其他存储介质中,以备后续分析或展示。常用的存储形式包括关系型数据库、NoSQL数据库、JSON文件等。 遵守规则: 为避免对网站造成过大负担或触发反爬虫机制,爬虫需要遵守网站的robots.txt协议,限制访问频率和深度,并模拟人类访问行为,如设置User-Agent。 反爬虫应对: 由于爬虫的存在,一些网站采取了反爬虫措施,如验证码、IP封锁等。爬虫工程师需要设计相应的策略来应对这些挑战。 爬虫在各个领域都有广泛的应用,包括搜索引擎索引、数据挖掘、价格监测、新闻聚合等。然而,使用爬虫需要遵守法律和伦理规范,尊重网站的使用政策,并确保对被访问网站的服务器负责。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大白砌墙

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值