实现简易Java网络爬虫

网络爬虫,即网络机器人或网页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. 根据指定的字符集把二进制流转成字符串,完成下载

1public static String downloadPage(String url) throws IOException{ 2 String content = null; 3 4 //创建一个客户端,类似于打开一个浏览器 5 //CloseableHttpClient httpclient = HttpClientBuilder.create().builder(); 6 DefaultHttpClient httpclient = new DefaultHttpClient(); 7 8 //创建一个GET方法,类似于在浏览器地址栏中输入一个地址 9 HttpGet httpget = new HttpGet(url); 10 11 //类似于在浏览器地址栏中输入回车,获得网页内容 12 HttpResponse response = httpclient.execute(httpget); 13 14 //查看返回的内容,类似于在浏览器查看源代码 15 HttpEntity entity = response.getEntity(); 16 if(entity != null){ 17 //读入内容流,并以字符串形式返回,这里指定网页编码是UTF-8 18 content = EntityUtils.toString(entity,"utf-8"); 19 EntityUtils.consume(entity); //关闭内容流 20 } 21 22 //释放连接 23 httpclient.getConnectionManager().shutdown(); 24 25 return content; 26} 27

Jsoup是一个功能十分强大的Java的HTML解析器,它支持使用DOM来查找、取出数据,也可以使用CSS选择器来查找、取出数据,还提供了类似于JQuery的操作方法来取出和操作数据。只需要一个jsoup.jar包即可。

1String url = "http://www.baidu.com"; 2Document doc = Jsoup.connect(url).get(); //解析的结果就是一个文档对象 3Elements links = doc.select("a[href]"); //带有href属性的a标签 4for(Element link: links){ //遍历每个链接 5 String linkHref = link.attr("href"); //得到href属性中的值,也就是URL地址 6 String linkText = link.text(); //得到锚点上的文字说明 7 System.out.println(linkHref+" "+linkText); //输出URL地址和锚点上的文字说明 8} 9
1当然,在Jsoup进行URL连接时可以进行连接参数的设置 2
1Document doc = Jsoup.connect("http://www.lietu.com/") 2.data("query","Java") //请求参数 3.userAgent("jsoup") //设置User-Agent 4.Cookie("auth","token") //设置Cookie 5.timeout(3000) //设置连接超时时间 6.post(); //使用POST方法访问URL 7
1如果遇到超链接中还有超链接,需要依次爬取的情况,只需封装后递归调用即可 2
1public static void extractList(String url) throws IOException{ 2 Document doc = Jsoup.connect(url).get(); //解析的结果就是一个文档对象 3 Elements links = doc.select("a[href]"); //带有href属性的a标签 4 for(Element link: links){ //遍历每个链接 5 String linkHref = link.attr("href"); //得到href属性中的值,也就是URL地址 6 if(linkHref.startsWith("http://list.xiu.com/") || linkHref.startsWith("http://brand.xiu.com/")){ 7 if(urlSeen.contains(linkHref)) 8 continue; 9 extractList(linkHref); //递归调用 10 }else if(linkHref.startsWith("http://item.xiu.com/product/")){ 11 if(urlSeen.contains(linkHref)) 12 continue; 13 getProduct(linkHref); //提取详细页中的商品信息 14 } 15 } 16} 17
1 Jsoup.connect下载网页非常方便简洁,但是没有多次重试的功能,因此可以使用HttpClient下载网页后把字符串传给Jsoup解析。 2

模式:HttpClient实现下载网页,用Jsoup解析网页。

1String url = "http://www.baidu.com"; 2String content = HttpUtil.getContent(url); 3Document doc = Jsoup.parse(content); 4

一般来说,还是建议先将网页中下载的数据存储入数据库中,再从数据库中提取数据。 按照上述流程,即可构造出一个简易的网络爬虫。

代码交流 2021