首页 > 代码库 > 使用HttpParser类解析网页

使用HttpParser类解析网页


之前发过一篇文章:利用String类制作简单的网络爬虫

http://blog.csdn.net/gfd54gd5f46/article/details/54729874

  • 这是是基于String类里的substring()方法对字符串进行截取,从而得到想要的内容。

  • 这种方法如果只是截取简单数据的话,还是可以实现的。

  • 但是如果我要获取指定的数据(这个数据可能成千上万条),这时后用String类里面的方法就会很麻烦,而且要编写的代码会变的非常多。





现在我们要引用一个网页解析的工具类来帮助我们更方便的解析网页。

下载 HtmlParser类

官方地址:http://htmlparser.sourceforge.net/

在线API文档:http://htmlparser.sourceforge.net/javadoc/index.html

下载地址:https://sourceforge.net/projects/htmlparser/files/

技术分享



进去htmlparser下载1.6的版本

技术分享



下载完成之后解压缩出来

技术分享


导入jar包


右键单击项目

技术分享



创建一个Folder ,名字为 lib


将 htmlparser.jar 拷贝进去

技术分享



右键项目->Properties->java Build Path

技术分享



添加一个jar包

技术分享



最后OK就可以了

在代码上创建一个 Parser 对象试试看看行不行

技术分享

这样就把引用了网上下载的jar包,现在就可以对网页进行解析了。


解析网页



这里随便找个 电影网站 来进行测试

http://www.dytt8.net


获取单个视频的下载链接

  • 进去 日韩电影 这里

技术分享



然后随便打开一个 电影 标题,我这里就选择第一个

  • 打开之后发现这个页面是介绍 电影的
/20170129/53099.html

技术分享



F12进去调试模式

  • 分析下载地址

技术分享



发现整个页面就只有一个ftp的标识

ftp://ygdy8:ygdy8@y219.dydytt.net:9239/[阳光电影www.ygdy8.com].蜡笔小新:梦境世界大突击.BD.720p.日国粤三语中字.mkv

技术分享



发现了规律之后,那我们是不是只提取含有ftp开头的字符串就可以了呢?

  • 代码实现
    /**
     *获取电影的下载地址
     */
    public static void  test1() {
        try {
            Parser parser = new Parser("http://www.dytt8.net/html/gndy/dyzz/20170208/53190.html");
            //提取所有匹配的节点保存到节点列表
            //LinkStringFilter("ftp")  节点字符串过滤器,过滤所有包涵 "ftp" 的字符串  
            NodeList nodeList = parser.extractAllNodesThatMatch(new LinkStringFilter("ftp"));
            //遍历节点列表
            for (int i = 0; i < nodeList.size(); i++) {
                //将节点列表的第一个元素保存到标签里
                LinkTag tag = (LinkTag) nodeList.elementAt(i);
                //打印标签
                System.out.println(tag.getLink());
            }   
        } catch (ParserException e1) {
            e1.printStackTrace();
        }
    }


运行之后确实是获取到下载地址

技术分享


2、获取单个列表里面所有的电影介绍页地址


我们知道每个电影的介绍页面都是不同的网页

比如刚刚的页面,它的后缀是:/html/gndy/dyzz/20170129/53099.html

分析一下页面源码:http://www.dytt8.net/html/gndy/dyzz/index.html

发现这个列表是在table里面的

技术分享



每行都有一个电影的各种信息

技术分享



那我们能不能获取一下每个页面的介绍地址呢?

“/html/gndy/dyzz/20170129/53099.html”




首先还是一样,分析一下规律

查找内容时发现在当前table下每个a标签都有一个class属性是“ulink

技术分享


发现了规律之后我们就用代码实现一下吧

  • 代码实现
/**
     * http://www.ygdy8.net/html/gndy/dyzz/index.html
     * 从网页里获取25个电影的介绍地址
     */
    public static void test2() {
        try {
            Parser parser = new 
Parser("http://www.ygdy8.net/html/gndy/dyzz/index.html");
//过滤所有class属性是"ulink"的标签
            NodeList nodeList = parser.extractAllNodesThatMatch(new 
HasAttributeFilter("class","ulink"));
            System.out.println("找到:" + nodeList.size() + "条数据。");
            for (int i = 0; i < nodeList.size(); i++) {
                //拿到节点的链接标签
                LinkTag tag = (LinkTag) nodeList.elementAt(i);
                System.out.println(tag.getLink());
            }

        } catch (ParserException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }
    }


这样就拿到个每个介绍页面的链接

技术分享


3、 获取所有的列表页面


刚刚第2步的时候已经拿到单个列表页面的所有介绍页面,那我们也可以获取所有的列表页面



同样,分析一下网页源码,找一下规律

技术分享



查找option标签可以发现 有161条数据

技术分享



再过滤一下里option包涵有value属性的总共有159个,因为前两个不是列表标签,所以找到的总共有157个

技术分享



知道了规律之后,我们就可以获取了

  • 代码实现
    /**
     * http://www.ygdy8.net/html/gndy/dyzz/index.html
     * 从网页获取157个电影分页的地址
     */
    public static void test3() {
        try {
            Parser parser = new Parser("http://www.ygdy8.net/html/gndy/dyzz/index.html");
            //获取所有包涵value属性的option标签
            NodeList nodeList = parser.extractAllNodesThatMatch(
                    new TagNameFilter("option")).extractAllNodesThatMatch(
                            new HasAttributeFilter("value"));
            //System.out.println("找到:" + nodeList.size() + "条数据。");
            for (int i = 0; i < nodeList.size(); i++) {
                //拿到第i个元素
                OptionTag tag = (OptionTag) nodeList.elementAt(i);
                //如果获取带有value属性的标签,并且标签里面包涵有list内容
                if (tag.getAttribute("value").contains("list")) {
                    System.out.println(tag.getAttribute("value"));
                }
            }

        } catch (ParserException e1) {
            e1.printStackTrace();
        }

技术分享


这样就成功拿到了所有的列表

实战


现在我要把这三个方法整合起来:

  • 1、 获取到所有列表

  • 2、 遍历每个列表的介绍页面

  • 3、 通过介绍页面获取下载地址



完整源码

package com.lingdu.htmlparser;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;

public class HtmlParserDemo {

    /**
     * 保存电影下载地址
     * @param i 第i条数据
     * @param content 内容
     * @param pathName 保存路径
     */
    public static void saveMovieDownloadAddress(int i, String content, String pathName) {
        if (!pathName.equals("")) {
            File fileName = new File(pathName);
            try {
                PrintWriter pw = new PrintWriter(new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileName,true),"UTF-8")));
                pw.println(i + " : "  + content);
                pw.flush();
                pw.close();
                System.out.println("保存------>" + content + "    成功!");
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (UnsupportedEncodingException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 3、通过介绍地址获取电影的下载地址
     */
    public static List<String> getDownloadUrl(String movieUrl) {
        List<String> list = new ArrayList<String>();
        try {
            Parser parser = new Parser("http://www.ygdy8.net" + movieUrl);
            //提取所有匹配的节点保存到节点列表
            //LinkStringFilter("ftp")  节点字符串过滤器,过滤所有包涵 "ftp" 的字符串  
            NodeList nodeList = parser.extractAllNodesThatMatch(new LinkStringFilter("ftp"));
            //遍历节点列表
            for (int i = 0; i < nodeList.size(); i++) {
                //将节点列表的第一个元素保存到标签里
                LinkTag tag = (LinkTag) nodeList.elementAt(i);
                //打印标签
                //System.out.println(tag.getLink());
                list.add(tag.getLink());

            }   
        } catch (ParserException e1) {
            e1.printStackTrace();
        }
        return list;
    }

    /**
     * 2、从网页里获取所有电影的介绍地址
     */
    public static List<String> getAllMoviePageFromOneList(String oneListUrl) {
        //保存所有电影的介绍地址
        List<String> list = new ArrayList<String>();
        try {
            Parser parser = new Parser("http://www.ygdy8.net/html/gndy/dyzz/" + oneListUrl);
            NodeList nodeList = parser.extractAllNodesThatMatch(new HasAttributeFilter("class","ulink"));
            System.out.println("找到:" + nodeList.size() + "条数据。");
            for (int i = 0; i < nodeList.size(); i++) {
                //拿到节点的链接标签
                LinkTag tag = (LinkTag) nodeList.elementAt(i);
                //System.out.println(tag.getLink());
                list.add(tag.getLink());
            }

        } catch (ParserException e1) {
            e1.printStackTrace();
        }
        return list;
    }


    /**
     * 1、从网页获取电影的分页的地址
     */
    public static List<String> getAllListFromUrl(String url) {
        //创建一个list集合用来存放所有的列表页面
        List<String> list = new ArrayList<String>();
        try {
            Parser parser = new Parser(url);
            //获取所有包涵value属性的option标签
            NodeList nodeList = parser.extractAllNodesThatMatch(
                    new TagNameFilter("option")).extractAllNodesThatMatch(
                            new HasAttributeFilter("value"));
            //System.out.println("找到:" + nodeList.size() + "条数据。");
            for (int i = 0; i < nodeList.size(); i++) {
                //拿到第i个元素
                OptionTag tag = (OptionTag) nodeList.elementAt(i);
                //如果获取带有value属性的标签,并且标签里面包涵有list内容
                if (tag.getAttribute("value").contains("list")) {
                    //System.out.println(tag.getAttribute("value"));
                    list.add(tag.getAttribute("value"));
                }
            }

        } catch (ParserException e1) {
            e1.printStackTrace();
        }

        //list_23_1.html
        return list;
    }

    /**
     * 整合逻辑
     * 将所有的方法集合运行
     */
    public static void logicIntegration() {
        //保存所有的分页列表的页面
        List<String> allList = getAllListFromUrl("http://www.ygdy8.net/html/gndy/dyzz/index.html");
        //保存所有电影页面地址
        List<String> allMoviePageUrl = new ArrayList<String>();

        //保存所有电影的下载地址
        List<String> allDownloadUrl = new ArrayList<String>();

        //统计次数
        int i = 0;
        for (String str1 : allList) {
            System.out.println("\n页面:-------------------->" + str1 + "--------------------");
            allMoviePageUrl = getAllMoviePageFromOneList(str1);
            for (String str2 : allMoviePageUrl) {
                allDownloadUrl = getDownloadUrl(str2);
                for (String str3 : allDownloadUrl) {
                    i += 1;
                    //Movie DownLoad Address.txt是文件名,可以自己定义
                    saveMovieDownloadAddress(i,str3,"Movie DownLoad Address.txt");
                    //System.out.println(str3);
                }
            }
        }
    }




    public static void main(String[] args) {
        logicIntegration();
    }
}



全部保存完毕!

技术分享

<script type="text/javascript"> $(function () { $(‘pre.prettyprint code‘).each(function () { var lines = $(this).text().split(‘\n‘).length; var $numbering = $(‘
    ‘).addClass(‘pre-numbering‘).hide(); $(this).addClass(‘has-numbering‘).parent().append($numbering); for (i = 1; i <= lines; i++) { $numbering.append($(‘
  • ‘).text(i)); }; $numbering.fadeIn(1700); }); }); </script>

    使用HttpParser类解析网页