java爬虫查找四川大学所有学院的网站的网址中的通知和新闻——以计算机学院为例

 

  1. 需求:查找四川大学所有学院的网站的网址中的通知和新闻——以计算机学院为例

     

  2. 流程图

 

  3. 具体步骤

      (1) 学院的主页为:http://cs.scu.edu.cn/ 获取该页面的所有内容(本文只获取新闻的具体内容,通知的只需要更改下正则表达式) 

      

 1 /**
 2      * 获取要抓取页面的所有内容
 3      * @param url 网页地址
 4      * @return
 5      */
 6     public static String sendGet(String url) {
 7         
 8         BufferedReader in = null;
 9         String result = "";
10         // 通过HttpClientBuilder创建HttpClient
11         HttpClientBuilder httpClientBuilder = HttpClientBuilder.create();
12         CloseableHttpClient client = httpClientBuilder.build();
13         
14         HttpGet httpGet = new HttpGet(url);
15         // 设置请求和传输超时时间
16         RequestConfig requestConfig = RequestConfig.custom()
17                 .setConnectTimeout(5000).build();
18         httpGet.setConfig(requestConfig);
19 
20         System.out.println(httpGet.getRequestLine());
21 
22         try {
23             HttpResponse httpResponse = client.execute(httpGet);
24 
25             int statusCode = httpResponse.getStatusLine().getStatusCode();
26 
27             // 响应状态
28             System.out.println("status:" + statusCode);
29             if (statusCode == HttpStatus.SC_OK) {
30                 // 获取响应的消息实体
31                 HttpEntity entity = httpResponse.getEntity();
32 
33                 // 判断实体是否为空
34                 if (entity != null) {
35                     System.out.println("contentEncoding:"
36                             + entity.getContentLength());
37 
38                     in = new BufferedReader(new InputStreamReader(
39                             entity.getContent(), "GBK"));
40 
41                     String line;
42                     while ((line = in.readLine()) != null) {
43                         // 遍历抓取到的每一行并将其存储到result里面
44                         result += line;
45                     }
46                 }
47             }
48         } catch (Exception e) {
49 
50             e.printStackTrace();
51         } finally {
52             try {
53                 client.close();
54                 if (in != null) {
55                     in.close();
56                 }
57             } catch (Exception e2) {
58                 e2.printStackTrace();
59             }
60         }
61         return result;
62     }

    (2) 使用正则表达式提取通知页面和新闻页面的地址

      指向新闻页的地址源码为:<MAP name=Map3><AREA shape=RECT target=_blank coords=498,27,539,37 href="/cs/xyxw/H9501index_1.htm">

      所以正则表达式为:coords=498,27,539,37 href=\"(.+?)\">

      

      指向通知页的地址源码为:<MAP name=Map6><AREA shape=RECT target=_blank coords=498,11,538,23 href="/cs/xytz/H9502index_1.htm"></MAP>

        所以正则表达式可以为:coords=498,11,538,23 href=\"(.+?)\">

      

 1   /**
 2      * 查找主页中的新闻和通知的URL
 3      * @param context  主页内容
 4      * @param type  查找类型
 5      * @return
 6      */
 7     public static String getURL(String context, int type) {
 8 
 9         Pattern pattern;
10         Matcher matcher;
11 
12         if (type == 0) {// 当type=0时,查找新闻
13             // 创建Pattern对象
14             pattern = Pattern.compile("coords=498,27,539,37 href=\"(.+?)\">");
15             // 创建Matcher对象,并匹配
16             matcher = pattern.matcher(context);
17 
18             if (matcher.find()) {// 查看是否找到,找到返回
19                 return "http://cs.scu.edu.cn" + matcher.group(1);
20             }
21         } else if (type == 1) {// 当type=1时,查找通知
22             pattern = Pattern.compile("coords=498,11,538,23 href=\"(.+?)\">");
23             matcher = pattern.matcher(context);
24             if (matcher.find()) {
25                 return "http://cs.scu.edu.cn" + matcher.group(1);
26             }
27         } else {
28             return "输入的type不正确";
29         }
31         return null;
32     }

     

    得到新闻和通知地址:

    a) 新闻页面地址为 http://cs.scu.edu.cn/cs/xyxw/H9501index_1.htm

    b) 通知页面地址为 http://cs.scu.edu.cn/cs/xytz/H9502index_1.htm

   (3)获取所有新闻的URL:以新闻为例

    

    新闻的具体内容的地址在源码中的表示:

          <A href=/cs/xyxw/webinfo/2016/06/1466645005004306.htm target=_blank>计算机学院(软件学院)第三届第六次双代会圆满举行</A></TD></TD><TD><DIV align=right><FONT size=2>[2016-06-30]

      所以正则匹配表达式为:<A href=/cs/xyxw/webinfo(.+?) target=_blank>

    

 1     /**
 2      * 查询具体新闻所在页面的所有URL
 3      * @param url
 4      * @return
 5      */
 6     public static List<String> getRealURL(String url) {
 7 
 8         // 存储URL地址
 9         List<String> list = new ArrayList<>();
10         // 获取的主页内容
11         String context = sendGet(url);
12         System.out.println(context);
13         // 匹配新闻地址的正则表达式
14         Pattern pattern = Pattern
15                 .compile("<A href=/cs/xyxw/webinfo(.+?) target=_blank>");
16         Matcher matcher = pattern.matcher(context);
17 
18         // 匹配url中的数字2(2表示页数,可以通过观察地址得出) :
19         //    http://cs.scu.edu.cn/cs/xyxw/H9501index_2.htm
20         //  http://cs.scu.edu.cn/cs/xyxw/H9501index_3.htm
21         Pattern patternNext = Pattern.compile("index_(.+?).htm");
22         Matcher matcherNext = patternNext.matcher(url);
23         
24         int i = 0; 
25         if (matcherNext.find()) {
26             System.out.println(matcherNext.group(1));
27             // 设置i为当前页数
28             i = Integer.parseInt(matcherNext.group(1));
29         }
30 
31         boolean isFind = matcher.find();
32 
33         while (isFind) {
34             while (isFind) {// 遍历当前页的所有新闻的URL
35                 // 将获取的URL存储到list中
36                 list.add("http://cs.scu.edu.cn/cs/xyxw/webinfo"
37                         + matcher.group(1));
38                 isFind = matcher.find();
39             }
40             
41             i++;
42             // 下一页地址
43             String nextUrl = "http://cs.scu.edu.cn/cs/xyxw/H9501index_" + i    + ".htm";
44             context = sendGet(nextUrl);
45             // 匹配新页面
46             matcher = pattern.matcher(context);
47             isFind = matcher.find();
48         }
49         return list;
50     }

 

      得到结果:

    (4)获取具体新闻页的信息:

      a)使用封装类:

      

 1 package com.huang.domain;
 2 
 3 import java.util.Date;
 4 
 5 public class Message {
 6 
 7     private String type; //类型是新闻还是通知
 8     
 9     private String title; //信息标题
10     
11     private Date date;    //信息发布时间
12     
13     private String pic; //相关图片
14     
15     private String context;    //具体信息内容
16     
17     public String getPic() {
18         return pic;
19     }
20     public void setPic(String pic) {
21         this.pic = pic;
22     }
23     
24     public String getTitle() {
25         return title;
26     }
27     public void setTitle(String title) {
28         this.title = title;
29     }
30     public String getContext() {
31         return context;
32     }
33     public void setContext(String context) {
34         this.context = context;
35     }
36     public Date getDate() {
37         return date;
38     }
39     public void setDate(Date date) {
40         this.date = date;
41     }
42     public String getType() {
43         return type;
44     }
45     public void setType(String type) {
46         this.type = type;
47     }
48     @Override
49     public String toString() {
50         return "Message [title=" + title + ", date=" + date + ", pic=" + pic
51                 + ", context=" + context + "]";
52     }   
56 }

    (b)获取新闻具体页的信息:

    

        

 1   /**
 2      * 获取所有新闻页和通知页具体信息
 3      * @param listUrl
 4      * @return
 5      */
 6     public static List<Message> getAllInformation(List<String> listUrl) {
 7 
 8         Pattern pattern;
 9         Matcher matcher;
10         // 存储查到的每条新闻
11         List<Message> list = new ArrayList<>();
12         
13         // 根据前面获取的所有页面的url,遍历所有的信息主页,获取相关信息
14         for (String url : listUrl) {
15 
16             Message message = new Message();
17             // 获取当页信息的全部信息
18             String context = sendGet(url);
19             // 获取标题
20             pattern = Pattern.compile("<DIV align=center> (.+?)</DIV>");
21             matcher = pattern.matcher(context);
22             if (matcher.find()) {// 设置标题
23                 message.setTitle(matcher.group(1));
24             }
25             // 获取日期
26             pattern = Pattern.compile("</SPAN> ([0-9].+?)<SPAN class=hangjc "
27                     + "style=\"LINE-HEIGHT: 30px\" valign=\"bottom\">");
28             matcher = pattern.matcher(context);
29             if (matcher.find()) {// 设置日期
30                 SimpleDateFormat format = new SimpleDateFormat(
31                         "yyyy-MM-dd HH:mm");//设置日期格式
32                 try {
33                     //将字符串转换成date类型
34                     Date date = format.parse(matcher.group(1));
35                     message.setDate(date);
36                 } catch (ParseException e) {
37                     System.out.println("日期格式不正确");
38                     e.printStackTrace();
39                 }
40             }
41             //获取图片
42             pattern = Pattern.compile("align=center src=\"(.+?).jpg\"");
43             matcher = pattern.matcher(context);
44             if (matcher.find()) {//设置图片
45                 message.setPic("http://cs.scu.edu.cn/" + matcher.group(1)
46                         + ".jpg");
47             }
48             //获取内容
49             pattern = Pattern.compile("<DIV id=BodyLabel>.+?</DIV>");
50             matcher = pattern.matcher(context);
51             if (matcher.find()) {//设置内容
52                 String result = matcher.group(0);
53                 //过滤一些内容中的标签
54                 result = result.replaceAll("&nbsp;", " ");
55                 result = result.replaceAll("<br>", "\r\n");
56                 result = result.replaceAll("<.*?>", "");
57                 message.setContext(result);
58             }
59             //将查询到的新闻添加到list中
60             list.add(message);
61         }
62         return list;
63     }

    

    (5)测试代码:

 1     public static void main(String[] args) {
 2         //获取计算机学院主页中的所有信息
 3         String context = Spider.sendGet("http://cs.scu.edu.cn/");
 4         System.out.println(context);
 5         //获取新闻所在页的地址
 6         String newsUrl = Spider.getURL(context, 0);
 7         //查找每个新闻的地址
 8         List<String> listUrl = Spider.getRealURL(newsUrl);
 9         System.out.println(listUrl);
10         //查到出每个新闻的内容
11         List<Message> messages = Spider.getAllInformation(listUrl);
12         
13         System.out.println(messages);
14         
15     }

 

  (java正则知识可以参考http://www.runoob.com/java/java-regular-expressions.html)

  

 

    

 

 

      

 

posted @ 2016-07-20 10:40  huangyichun  阅读(891)  评论(0编辑  收藏  举报