网络爬虫,即网络机器人或网页spider。通常用来爬取网页数据与信息。随着蜘蛛自主爬行得越来越远,其挖掘的数据也便越来越多。
在现今计算机界通常的认识是python实现网络爬虫有着得天独厚的优势,实现容易快捷,且挖掘效率高。然而随着Java语言的发展与完善,一批又一批Java开发者为Java实现网络爬虫构造了诸多框架与jar包。这其中就包括heritrix,crawler4j等。
Java实现网络爬虫,说大不大,说小不小。小到只需要使用Java SE中的net包即可实现,大到需要使用朴素贝叶斯等机器学习算法实现。
学习使用Java开发网络爬虫的筒子们通常学到的第一课就是使用一个java.net.URL去下载网页源代码,然后再用输入流将爬取到的信息写入文件中。然而尽管java.net包提供了通过HTTP访问资源的基本功能,但它没有提供全面的灵活性和套接字、连接池等开发爬虫需要的功能。
因此在实际开发中通常使用HttpClient下载网页,用Jsoup解析网页。
HttpClient获取网页内容的过程:
1. 创建一个CloseableHttpClient类的实例
2. 使用这个实例执行HTTP请求,得到一个HttpResponse的实例
3. 通过HttpResponse的实例得到返回的二进制流,二进制流封装在HttpEntity中
4. 根据指定的字符集把二进制流转成字符串,完成下载
public static String downloadPage(String url) throws IOException{
String content = null;
//创建一个客户端,类似于打开一个浏览器
//CloseableHttpClient httpclient = HttpClientBuilder.create().builder();
DefaultHttpClient httpclient = new DefaultHttpClient();
//创建一个GET方法,类似于在浏览器地址栏中输入一个地址
HttpGet httpget = new HttpGet(url);
//类似于在浏览器地址栏中输入回车,获得网页内容
HttpResponse response = httpclient.execute(httpget);
//查看返回的内容,类似于在浏览器查看源代码
HttpEntity entity = response.getEntity();
if(entity != null){
//读入内容流,并以字符串形式返回,这里指定网页编码是UTF-8
content = EntityUtils.toString(entity,"utf-8");
EntityUtils.consume(entity); //关闭内容流
}
//释放连接
httpclient.getConnectionManager().shutdown();
return content;
}
String url = "http://www.baidu.com";
Document doc = Jsoup.connect(url).get(); //解析的结果就是一个文档对象
Elements links = doc.select("a[href]"); //带有href属性的a标签
for(Element link: links){ //遍历每个链接
String linkHref = link.attr("href"); //得到href属性中的值,也就是URL地址
String linkText = link.text(); //得到锚点上的文字说明
System.out.println(linkHref+" "+linkText); //输出URL地址和锚点上的文字说明
}
当然,在Jsoup进行URL连接时可以进行连接参数的设置
Document doc = Jsoup.connect("http://www.lietu.com/")
.data("query","Java") //请求参数
.userAgent("jsoup") //设置User-Agent
.Cookie("auth","token") //设置Cookie
.timeout(3000) //设置连接超时时间
.post(); //使用POST方法访问URL
如果遇到超链接中还有超链接,需要依次爬取的情况,只需封装后递归调用即可
public static void extractList(String url) throws IOException{
Document doc = Jsoup.connect(url).get(); //解析的结果就是一个文档对象
Elements links = doc.select("a[href]"); //带有href属性的a标签
for(Element link: links){ //遍历每个链接
String linkHref = link.attr("href"); //得到href属性中的值,也就是URL地址
if(linkHref.startsWith("http://list.xiu.com/") || linkHref.startsWith("http://brand.xiu.com/")){
if(urlSeen.contains(linkHref))
continue;
extractList(linkHref); //递归调用
}else if(linkHref.startsWith("http://item.xiu.com/product/")){
if(urlSeen.contains(linkHref))
continue;
getProduct(linkHref); //提取详细页中的商品信息
}
}
}
Jsoup.connect下载网页非常方便简洁,但是没有多次重试的功能,因此可以使用HttpClient下载网页后把字符串传给Jsoup解析。
模式:HttpClient实现下载网页,用Jsoup解析网页。
String url = "http://www.baidu.com";
String content = HttpUtil.getContent(url);
Document doc = Jsoup.parse(content);
一般来说,还是建议先将网页中下载的数据存储入数据库中,再从数据库中提取数据。
按照上述流程,即可构造出一个简易的网络爬虫。