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"));
}
}
}
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"));
}
}
}