一个简单网络爬虫的实现
——抓取网易新闻
这次来指定一个信息量稍大一点的抓取目标——网易新闻(国内新闻) http://news.163.com/domestic/
这次要达到的目标:
1. 提取有用文本信息
2. 将新闻中所包含的图片信息保存在本地
3. 构建新的HTML文件,其中只包含有新闻主体内容与对应的图片信息
首先当然是通过Jsoup与给定的种子URL建立连接,获得网易新闻(国内新闻)首页的Document,并且在其中筛选出链接,这在上一篇已经提过;然而,我们发现这里得到的许多URL并不是我们想要的新闻内容,而是一些广告的链接,处理办法很简单,我们在这里所要做的仅仅是一个简单的字符串匹配问题,只保留下我们需要的那部分链接即可。
得到了需要的链接之后,依旧是按照之前的方法去访问那个URL,获取它所对应页面的Document,接下来就是在这个页面中来提取出有用的信息(新闻文本内容)了:
这是得到的新闻页面的HTML:
我们通过对新闻页面的HTML分析得知,所有的新闻文本内容都是在id为"endText"这个层中,对应的我们的代码该如何来进行筛选呢?
- Element endText = doc.getElementById("endText");
这样便得到了id为"endText"的一个Element节点,这个节点中也存在一些方法可以供我们来提取相应的信息,例如:
- String Text = endText.text(); //获取endText中的文本内容
- String HTML = endText.html(); //获取endText对应的HTML内容
这样一来就达成了第一个目标,提取出了有效地文字信息。
当我们将获取到页面的HTML文件保存在本地,通过浏览器打开时发现可以查看图片啊、视频等信息,可是当断开网络后就发现这些信息无法查看了,那是因为在网页的HTML中对于图片的那个标签中写有一个URL,这个URL对应的就是这个图片的地址,每当我们打开网页时,就会从对应的这个URL中加载图片展现在页面上,当没有了网络连接他无法从对应的URL中加载图片自然就没有办法显示了,现在我们要做的就是讲这个URL对应的图片保存在本地。
试想,同样是URL,我们是否可以通过抓取网页那样的方法去对待图片呢? 不妨试试看
很显然,是不可以的,从报错情况中可以看到是因为类型不对的缘故,也就是图片信息不能通过这样的方法来获取,那该怎么办呢?
以下是百度百科中对URL的定义
即,每一个互联网上的资源都对应有一个URL,也就是只要有这个URL就可以访问到对应的信息,Java中有一个URL类,它提供了许多对URL的处理方法,我注意到这样一个方法:
这个方法返回了一个从对应URL读入的字节流数据,也就是说图片信息可以通过这种方法以字节流的形式返回回来,我们只需要在本地对该字节流进行保存即可,还想着Java的i/o包中提供的很麻烦的方法么? 别忘了我们的FileUtils
FileUtils中还有这样一个方法:
- URL jpg = new URL(jpgUrl);
- InputStream is = jpg.openStream();
- FileUtils.copyInputStreamToFile(is, new File("JPG", "test.jpg"));
首先根据jpgUrl实例化了一个URL的对象jpg,然后调用其中的openStream()方法读取到jpgUrl对应的图片信息的字节流数据,最后通过FileUtils.copyInputStreamToFile()方法将is中保存的字节流数据保存在本地的JPG目下的"test.jpg"文件中。
OK,第二个目标达成,图片信息已经可以保存在本地了,那么第三步,重新整理得到信息,构建一个新的HTML。
这一步其实并不复杂,只要将得到的信息插入到他们应该存在的位置即可,例如:
- Document DocNew = Jsoup.parse("<html><head><title>"+title+"</title></head><body>"+HTML+"</body></html>");
- Elements imgs = DocNew.select("img[src]");
- for ( Element img:imgs ) {
- img.attr("src", ImgPath);
- }
第一步是将一个全新的HTML字符串实例化出一个Document对象,其中的title是页面的标头,HTML是上面获得的新闻正文内容对应的HTML,这其中便包含着图片的标签,通过下面的循环,将所有的<img
src=" ">中src的路径指定为ImgPath(图片本地路径)即可,将这样的HTML保存到本地后,再次以浏览器方式打开,就可以看到只有文字信息与图片信息这些有用的内容了,并且在没有网络的情况下依旧可以访问哦~
好了,这次的目标达成,继续加油!