java爬取天涯社区

package com.lyl.spider;


import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;


/**
 * 功能:实现一个简单的单机爬虫,爬取天涯社区
 * 作者:liuyanlin
 * 地址:成都锦江
 * 日期:2017-03-22
 */
public class TianyaSpider {
/**
* 爬虫爬取步骤:
* 1,根据一个起始url地址下载一个网页,这里做的是从天涯社区的首页地址作为入口,进行跟踪爬取
* 2,解析下载下来的网页内容,提取需要的数据、
* 3,对提取出来的数据进行处理
* 注:这里我采用的是正则匹配
*/

//1.下载网页,获取源码,参数:urlString 传一个url地址进去,返回网页源码字符串
public String getHtml(String urlString){
try {
        StringBuffer html = new StringBuffer();//创建一个字符串缓冲对象
        URL url = new URL(urlString);// 打开到这个URL的流
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        InputStreamReader isr = new InputStreamReader(conn.getInputStream());
        BufferedReader br = new BufferedReader(isr);//创建一个缓冲读取对象
        String temp;
        //这个循环的作用就是循环读取流里面的每一行数据,利用字符串缓冲对象,依次拼接,最终拼接成一个完整的html代码
        while ((temp = br.readLine()) != null) {
        html.append(temp).append("\n");
        }
        br.close();
        isr.close();
        return html.toString();
        } catch (Exception e) {
        e.printStackTrace();
        System.err.println("进入这里,恭喜你,代码有错,异常信息为:"+e);
        return null;
        }
}

//2.解析网页源码,提取自己想要的内容,这里我返回的是一个list,list里面存的是map,一个map代表一条信息,包含标题,类型,作者,时间
public List<Map<String, String>> analyticalData(String html){
//创建一个list集合对象,用于存储要返回的数据
List<String> data_list=new ArrayList<>();
//定义一个新闻列表的正则匹配表达式字符串,通过浏览器分析,得出天涯社区的新闻信息都是放在td标签里面的
String news_list= "<td .*?>([\\s\\S]*)</td>";
//将匹配新闻列表的正则字符串编译成可以执行的正则对象
        Pattern pattern_newList= Pattern.compile(news_list);
        //匹配
        Matcher matcher_newList= pattern_newList.matcher(html);
        //匹配出来的全部新闻列表字符串
        String str="";
        while(matcher_newList.find()){
        str=matcher_newList.group(0);
        }
//        System.out.println(str);
        //分割匹配出来的新闻列表字符串为数组,然后提提取需要的字段数据,你可以打印一哈上面我注释掉的str看一下数据结构
        String [] items;
        items=str.split("</tr>");
        //用来存储提取出来的数据list
        List<Map<String, String>>list = new ArrayList<Map<String,String>>();
        //循环去提取数据,下面的正则表达式提取原理和上面的一样
        for (String tr_str : items) {
        Map<String, String> map=new HashMap<>();
        //-------------------提取标题----------------------------
        String title= "<a href=\"/post.*? target=\"_blank\">([\\s\\S]*?)</a>";
        Pattern pattern_title= Pattern.compile(title);
        Matcher matcher_title= pattern_title.matcher(tr_str);
        while(matcher_title.find()){
            map.put("title", matcher_title.group(0));
            }
        //------------------提取新闻帖子类型------------------------
        String type= "<span class=\"face\" title=\"([\\s\\S]*?)\">([\\s\\S]*?)</span>";
        Pattern pattern_type= Pattern.compile(type);
        Matcher matcher_type= pattern_type.matcher(tr_str);
        while(matcher_type.find()){
            map.put("type", matcher_type.group(0));
            }
        //------------------提取作者-------------------------------
        String author= "<a href=\"http://www.*? target=\"_blank\" class=\"author\">([\\s\\S]*?)</a>";
        Pattern pattern_author= Pattern.compile(author);
        Matcher matcher_author= pattern_author.matcher(tr_str);
        while(matcher_author.find()){
            map.put("author", matcher_author.group(0));
            }
        //------------------提取发布时间---------------------------
        String date= "<td title=\"\\d{4}-\\d{2}-\\d{2} .*?>([\\s\\S]*?)</td>";
        Pattern pattern_date= Pattern.compile(date);
        Matcher matcher_date= pattern_date.matcher(tr_str);
        while(matcher_date.find()){
            map.put("date", matcher_date.group(0));
            }
        //将存储了一条信息的map添加到list里面
        list.add(map);
       
}
        return list;  
}

//3.处理数据,在这里你可以将数据存入数据库或者循环打印等等,这里的list是上面解析提取出来的数据列表
public void handleItem(List<Map<String, String>> list){
//这里我就只做了个循环打印出数据的
for (Map<String, String> map : list) {
System.out.println("--------------------信息----------------");
System.out.println("标题:"+map.get("title"));
System.out.println("类型:"+map.get("type"));
System.out.println("作者:"+map.get("author"));
System.out.println("时间:"+map.get("date"));

}

}

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

小牛牛先生

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

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

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

打赏作者

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

抵扣说明:

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

余额充值