前段时间公司分给我一个爬虫任务,由于自己没怎么接触过,只好一边学一边用,现在把用到的爬虫知识跟大家分享一下!
先来理解什么是爬虫吧!
爬虫(又被称为网页蜘蛛,网络机器人,在FOAF社区中间,更经常的称为网页追逐者),是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本。另外一些不常使用的名字还有蚂蚁、自动索引、模拟程序或者蠕虫。
对于我的理解就是从别人的网站爬取数据或内容的一种工具!
好了现在我们一起用URLConnection 来爬取中国知网首页的一些数据吧!
首先定义一个工具类,来保存要爬取网页的源代码,就是爬取下面这一大坨html静态代码。
关键部分还是得用URLConnection ,通过io流来获取网页的源代码。SendGet方法里面有两个参数,一个是url这个就是要爬取的地址,param这个参数就是网页的编码格式,如果不设置这个编码格式有时候编码匹配不上,爬下来的数据就会出现乱码。在上面看到的网页源代码中第四行有一个content=“text/html; charset=utf-8" 可以看出知网的编码格式是utf-8,我们传一个utf-8就行了。
/**
* 爬虫工具类
* @param url 传入连接地址
* @param param 设置网页编码格式
* @return
*/
static String SendGet(String url,String param) {
// 定义一个字符串用来存储网页内容
String result = "";
// 定义一个缓冲字符输入流
BufferedReader in = null;
try {
// 将string转成url对象
URL realUrl = new URL(url);
// 初始化一个链接到那个url的连接
URLConnection connection = realUrl.openConnection();
// 开始实际的连接
connection.connect();
// 初始化 BufferedReader输入流来读取URL的响应
in = new BufferedReader(new InputStreamReader(
connection.getInputStream(), param));
// 用来临时存储抓取到的每一行的数据
String line;
while ((line = in.readLine()) != null) {
// 遍历抓取到的每一行并将其存储到result里面
result += line;
}
} catch (Exception e) {
System.out.println("发送GET请求出现异常!" + e);
e.printStackTrace();
}
// 使用finally来关闭输入流
finally {
try {
if (in != null) {
in.close();
}
} catch (Exception e2) {
e2.printStackTrace();
}
}
return result;
}
下面我们来测试一下,看能不能爬到这个网页源代码呢?
public static void main(String[] args) {
String html=SendGet("http://www.cnki.net/","utf-8");
System.out.println(html);
}
运行一下可以看到源代码爬取下来了。
有了这些源代码当然要从中提取数据
接下来我们就从这些源代码中提取一些数据
来看看首页,我们提取首页中红色框框里面的数据吧!
要爬取里面的数据,我建议还是用正则匹配比较好!
先在网上找一个正则测试工具,个人觉得这个工具比较好!
我们先把源代码放到这个工具里
找到要匹配的数据
写上正则,可以看到匹配了一条数据
由于这数据比较特殊,我就打算用两次正则来匹配里面的数据,一条正则匹配我感觉还是匹配不到精准的数据,下面这只是把整个ul标签里面的所有内容拿到
不会写正则的宝宝们,分享一下我的正则经验,刚开始我对正则也是一头雾水,后来用心把正则语法好好看了一遍,动手写了几个,正则基本上就没问题了,其实正则只要记住几个括号,和他的一些语法很好写的,小括号代表:要匹配的内容,中括号代表:范围,大括号代表:数量;
下面代码测试一下
public static void main(String[] args) {
//获取源代码
String html=SendGet("http://www.cnki.net/","utf-8");
//定义一个字符串用来第一次匹配到的数据
String html1="";
// 写入正则用来匹配名称
Pattern NamePattern = Pattern.compile("<ul\\s+style=\"padding-right:0;\"\\s+class=\"col1\">(.+?)</ul>");
Matcher NameMatcher = NamePattern.matcher(html);
//迭代得到第一次匹配到的数据
while(NameMatcher.find()){
html1+=NameMatcher.group(1);
}
//执行第二次匹配
Pattern NameTwoPattern = Pattern.compile("<li><a.+?>(.+?)</a>");
Matcher NameTwoMatcher = NameTwoPattern.matcher(html1);
//迭代得到第二次匹配到的数据
while(NameTwoMatcher.find()){
String name=NameTwoMatcher.group(1);
//输出结果
System.out.println(name);
}
}
可以看到,获取到的数据和刚刚红色框框里面的数据是一样的
看看好像有什么问题,第一条记录怎么还有一个html标签,好吧!下面来改一下代码,把标签去掉
public static void main(String[] args) {
//获取源代码
String html=SendGet("http://www.cnki.net/","utf-8");
//定义一个字符串用来第一次匹配到的数据
String html1="";
// 写入正则用来匹配名称
Pattern NamePattern = Pattern.compile("<ul\\s+style=\"padding-right:0;\"\\s+class=\"col1\">(.+?)</ul>");
Matcher NameMatcher = NamePattern.matcher(html);
//迭代得到第一次匹配到的数据
while(NameMatcher.find()){
html1+=NameMatcher.group(1);
}
//执行第二次匹配
Pattern NameTwoPattern = Pattern.compile("<li><a.+?>(.+?)</a>");
Matcher NameTwoMatcher = NameTwoPattern.matcher(html1);
//迭代得到第二次匹配到的数据
while(NameTwoMatcher.find()){
String name=NameTwoMatcher.group(1);
//去除结果中的html标签
name=name.replaceAll("<sup>新!</sup>","" );
//输出结果
System.out.println(name);
}
}
在运行一下,标签没了