java爬虫实战(1):抓取信息门户网站中的图片及其他文件并保存至本地

java爬虫实战(1):抓取新闻网站中的图片和文件并保存至本地

本实战仅作为学习和技术交流使用,转载请注明出处;本实战中的代码逻辑编写参考《自己动手写网络爬虫》一书,本书提供的章节源码


由于是第一篇实战,因此此处将较为详细的从基础讲解java爬虫原理及相关实现技术。


网页抓取基础

网页抓取的原理其实并不是想象的那般神秘和复杂,简单的说便是将用户想获取到的信息从网页端保存到本地的一个操作过程。但是这个过程的一个重要问题便是:如何抓?
普通用户打开浏览器,输入网站的url便能进行网页访问。而这个url是什么?相信对于网络编程有过相关认识的人一定很了解,此处简要介绍。url是指上只是一个简单的字符串,如http://www.baidu.com,称为统一资源定位符,其由三个部分组成:
· 协议
· 主机IP地址
· 主机资源的具体地址,如目录和文件名
(具体细节并不在这里赘述)
而要想抓取网页上的内容,实际上是抓取服务器上资源,其过程就是通过URL定位到制定服务器上,将相应服务器上的资源通过http响应机制传回到本地,而抓取网页所要做的根本在于将request请求发送至服务器上,服务器做出response响应,我们将该响应经过相应处理,便能得到想要的资源。
对于网页抓取,我们更习惯称其为“爬虫”,亦或是“Robot”。在爬虫领域,最出名的当然是google搜索引擎(虽然baidu也很不错,但其商业性质实在……),而作为我们普通大众而言,想实现爬虫,其技术门槛并没有那么难。其原因根本在于使用的人多的跟“米”一样,因此你可以在网上找到各式各样的教材,材料,源码,框架等等。当然实现像google一样的搜索引擎并不是一朝一夕的事!我们常见的大众爬虫的实现更多的基于Python,Python因为其语言的特殊性,使得其在爬虫领域得到广泛的应用。当然,相应的java所实现爬虫也不在少数,著名的爬虫框架则是Apache的Nutch,结合Lucene使用,将实现一个非常强大的搜索引擎。
对于java实现爬虫常见的便是通过HttpClient和HtmlParser分别进行网络通信和html页面分析,因此实现一个简单的java爬虫技术门槛并不高,只要你学会了他们,便算是入门了。

HttpClient

HttpClient是Apache Jakarta Common下的子项目,用来提供高效的、最新的、功能丰富的支持HTTP协议的客户端编程工具包,并且它支持HTTP协议最新的版本和建议。HttpClient已经应用在很多的项目中,比如Apache Jakarta上很著名的另外两个开源项目Cactus和HTMLUnit都使用了HttpClient。
下载地址: http://hc.apache.org/downloads.cgi
使用HttpClient发送请求、接收响应很简单,一般需要如下几步即可。
1. 创建HttpClient对象。
2. 创建请求方法的实例,并指定请求URL。如果需要发送GET请求,创建HttpGet对象;如果需要发送POST请求,创建HttpPost对象。
3. 如果需要发送请求参数,可调用HttpGet、HttpPost共同的setParams(HetpParams params)方法来添加请求参数;对于HttpPost对象而言,也可调用setEntity(HttpEntity entity)方法来设置请求参数。
4. 调用HttpClient对象的execute(HttpUriRequest request)发送请求,该方法返回一个HttpResponse。
5. 调用HttpResponse的getAllHeaders()、getHeaders(String name)等方法可获取服务器的响应头;调用HttpResponse的getEntity()方法可获取HttpEntity对象,该对象包装了服务器的响应内容。程序可通过该对象获取服务器的响应内容。
实现实例

/**
*将抓取的网页下载到本地
*/
        String filePath = null;
        /* 1.生成 HttpClinet 对象并设置参数 */
        HttpClient httpClient = new HttpClient();
        // 设置 Http 连接超时 5s
                httpClient.getHttpConnectionManager().getParams().setConnectionTimeout(5000);
        /* 2.生成 GetMethod 对象并设置参数 */
        // 
        GetMethod getMethod = new GetMethod(url);
        // 设置 get 请求超时 5s
    getMethod.getParams().setParameter(HttpMethodParams.SO_TIMEOUT, 5000);
        // 设置请求重试处理
        getMethod.getParams().setParameter(HttpMethodParams.RETRY_HANDLER,
        new DefaultHttpMethodRetryHandler());
        /* 3.执行 HTTP GET 请求 */
        try {
            int statusCode = httpClient.executeMethod(getMethod);
            // 判断访问的状态码
            if (statusCode != HttpStatus.SC_OK) {
                System.err.println("Method failed: "
                        + getMethod.getStatusLine());
                filePath = null;
            }
            /* 4.处理 HTTP 响应内容 */
            byte[] responseBody = getMethod.getResponseBody();// 读取为字节数组
            // 根据网页 url 生成保存时的文件名
            filePath = "temp\\"
                    + getFileNameByUrl(url, getMethod.getResponseHeader(
                            "Content-Type").getValue());
            saveToLocal(responseBody, filePath);
        } catch (HttpException e) {
            // 发生致命的异常,可能是协议不对或者返回的内容有问题
            System.out.println("Please check your provided http address!");
            e.printStackTrace();
        } catch (IOException e) {
            // 发生网络异常
            e.printStackTrace();
        } finally {
            // 释放连接
            getMethod.releaseConnection();
        }
        return filePath;

正则表达式

正则表达式是字符提取的一个重要技术手段。关于正则表达式的细节,可以百度,对于java而言,实现正则提取也很简单,提供如下实例:

public boolean find(String regex,String url){
        //匹配以文件形式结尾的url
        //regex : ".*\\.(rar|png|jpg|bmp|gif|doc|zip|xls|zip|ZIP|PDF|DOC|JPG|JPEG|PNG|GIF)"
        //url : http://news.twt.edu.cn//default2010B/twt1/img/resourceIcon5.png
        Pattern pattern = Pattern.compile(regex);
        //Pattern类即为正则表达式
        Matcher matcher = pattern.matcher(url);
        //对传入的url进行字符提取和匹配,matches()为匹配,group()则为提取
        if(matcher.matches())
            return true;//如果匹配成功
        else
            return false;
    }

HtmlParser

HtmlParser是html解析器中的一种,本实战纯粹只为实现而已,并没有说HtmlParser更好用,反而现在用的更加流行的则是Jsoup,同样地,二者都能够实现对于Html各个节点标签进行解析。
HtmlParser的关键步骤也同样简单,分为:
(1)通过Parser类创建一个解释器
(2)创建Filter或者Visitor
(3)使用parser根据filter或者visitor来取得所有符合条件的节点
(4)对节点内容进行处理
实现代码:

public class HtmlParserTool {
    // 获取一个网站上的链接,filter 用来过滤链接
    public static Set<String> extracLinks(String url, LinkFilter filter) {

        Set<String> links = new HashSet<String>();
        try {
            Parser parser = new Parser(url);
            parser.setEncoding("utf-8");
            // 过滤 <frame >标签的 filter,用来提取 frame 标签里的 src 属性所表示的链接
            NodeFilter frameFilter = new NodeFilter() {
                public boolean accept(Node node) {
                    if (node.getText().startsWith("frame src=")||node.getText().contains("img ")) {
                        return true;
                    } else {
           
  • 3
    点赞
  • 17
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值