使用HttpParser类解析网页

2023-05-16


之前发过一篇文章:利用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/

1



进去htmlparser下载1.6的版本

2



下载完成之后解压缩出来

3


导入jar包


右键单击项目

4



创建一个Folder ,名字为 lib


将 htmlparser.jar 拷贝进去

5



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

6



添加一个jar包

7



最后OK就可以了

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

8

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


解析网页



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

http://www.dytt8.net


获取单个视频的下载链接

  • 进去 日韩电影 这里

9



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

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

10



F12进去调试模式

  • 分析下载地址

11



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

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

12



发现了规律之后,那我们是不是只提取含有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();
        }
    }


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

13


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


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

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

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

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

14



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

15



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

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




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

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

16


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

  • 代码实现
/**
     * 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();
        }
    }


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

17


3、 获取所有的列表页面


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



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

18



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

19



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

20



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

  • 代码实现
    /**
     * 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();
        }

21


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

实战


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

  • 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();
    }
}



全部保存完毕!

22

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用HttpParser类解析网页 的相关文章

  • pixhawk开发环境

    Windows 7 64bit 软件安装 首先 xff0c 需要安装一些软件 xff0c CMake 32位的Java jdk以及PX4 Toolchain Installer CMake的话笔者使用的是CMake 3 3 2 win32
  • Pixhawk-信息流浅解析

    根深方能叶茂 在等待的日子里 xff0c 刻苦读书 xff0c 谦卑做人 xff0c 养得深根 xff0c 日后才能枝叶茂盛 Better 根爷 之前我们已经谈到系统框架 xff0c 之前谈到了定制自己功能的两部 xff1a 添加模块和修改
  • Python跨进程共享数据/对象

    1 跨进程共享方式 在multiprocess库中 xff0c 跨进程对象共享有三种方式 xff1a xff08 1 xff09 第一种仅适用于原生机器类型 xff0c 即python ctypes当中的类型 xff0c 这种在mp库的文档
  • Pixhawk-姿态解算-互补滤波

    根深方能叶茂 在等待的日子里 xff0c 刻苦读书 xff0c 谦卑做人 xff0c 养得深根 xff0c 日后才能枝叶茂盛 Better 根爷 终于说到了正题 xff0c 姿态解算这一部分很重要 xff0c 主要的基础就是惯性导航和多传感
  • Pixhawk-姿态解算源码注释

    根深方能叶茂 在等待的日子里 xff0c 刻苦读书 xff0c 谦卑做人 xff0c 养得深根 xff0c 日后才能枝叶茂盛 Better 根爷 这一部分是我在看源码时 xff0c 自己注释的一点笔记 xff0c 现在直接贴上来 当然这其中
  • Pixhawk-串级pid介绍

    根深方能叶茂 在等待的日子里 xff0c 刻苦读书 xff0c 谦卑做人 xff0c 养得深根 xff0c 日后才能枝叶茂盛 Better 根爷 鉴于串级PID在pixhawk系统中的重要性 xff0c 无论是误差的补偿 xff0c 如姿态
  • pixhawk串口读取传感器数据

    1 Pixhawk板上串口说明 xff1a 测试 使用Pixhawk板上TELEM2接口的USART2 xff0c 对应的Nuttx UART设备文件尾 dev ttyS2 xff1a 2 读取数据测试 步骤 xff1a 在Firmware
  • Android调用系统自带的文件管理器进行文件选择

    这几天在做的项目网盘 上传时需要用到调用系统自带的文件管理器来选择文件 xff0c 后来就在考虑怎么调用 xff0c 网上也搜了很久 xff0c 没有很好的解决方法 xff0c 后来在一瞬间发现了一篇不错的文章 xff0c 借鉴了一下代码
  • Android下如何读取文件的内容

    唉 xff0c 尝试了好半天了 xff0c 才弄懂 xff0c 1 首先权限的问题 我们需要在根文件中添加权限 lt uses permission android name 61 34 android permission WRITE E
  • Mavlink地面站编写之二–Mission PLanner地面站构架分析之MAVLINK航点读写

    转载请注明出处 http www amovauto com 阿木社区 玩也要玩的专业 xff01 3DR这个地面站还是非常专业的 xff0c 最近研究MAVLINK通信协议 就来分析下Mission planner的构架 至于Msissio
  • Mavlink地面站编写之三–Mission PLanner地面站构架分析之MAVLINK航点写入

    转载注意出处 xff1a http www amovauto com p 61 601 more 601 阿木社区 玩也要玩的专业 xff01 我们知道了怎么利用mavlink读取航点 xff0c 那么如果我们要写入航点 xff0c 也是一
  • Mavlink地面站编写之四-Mission Planner中ProgressReporterDialogue和读串口线程serialreaderthread的分析

    转载请注明出处 http www amovauto com p 61 660 阿木社区 xff0c 玩也要玩的专业 QQ群 526221258 ProgressReporterDialogue 这个对话框很有意思 xff0c 在MP中连接阶
  • Mavlink地面站编写之八–MAVLINK消息自定义

    PIXHAWk MAVLINK消息自定义 对于PIXHAWK这个系统来讲 xff0c MAVLINK是个小型的数据通信协议 xff0c 负责地面站和飞控本身的数据交互和地面站向飞控发送数据指令 前面的文章已经讲过MAVLINK这个数据格式解
  • Python参数校验工具:validate.py

    一直都在找一个比较好用的参数校验工具包 xff08 Python xff09 xff0c 这次终于找到了就做个记录 包名 xff1a validate py 安装方式 xff1a xff08 pip已收入 当前最新版本是1 3 0 xff0
  • Mavlink-1-概述介绍

    1 MAVLink简介 MAVLink xff08 Micro Air Vehicle Link xff0c 微型空中飞行器链路通讯协议 xff09 是无人飞行器与地面站 xff08 Ground Control Station xff0c
  • PX4位置控制offboard模式说明

    offboard模式的开发及应用 一 px4固件的模式 px4固件支持10几种飞行模式 xff0c 从代码结构上分析 xff0c 分为基本模式 自定义模式和自定义子模式 1 基本模式 基本模式又分为 xff0c 位置控制模式 自稳模式 手动
  • Nuttx启动过程

    start 处理器执行的第一条指令 v stm32 clockconfig 初始化时钟 v rcc reset 复位rcc stm32 stdclockconfig 初始化标准时钟 rcc enableperipherals 使能外设时钟
  • 飞控打信息打印

    如果打印到地面站可以使用mavlink log critical mavlink log critical mavlink log pub local 34 HIL platform Connect to simulator before
  • console和nsh的区别

    PX4在调试过程中 console口和NSH口原来功能不一样 xff0c Console只是负责往外吐数据 xff0c 比如打印飞控启动的过程 xff0c 或者输出源码中warnx或者printf这样的打印信息 而NSH飞控上电的启动过程并
  • C++ Primer 好不好?投票呗

    我的C 43 43 Primer 11好不好 xff1f 投票呗 为了能写出更好的C 43 43 Primer xff0c 我在这里向大家问一下 xff1a 我写得好不好 xff1f 认为好的选上面 xff0c 认为不好的选下面 xff0c

随机推荐

  • C++Primer 非常适合入门

    C 43 43 Primer 非常适合入门 就像题目所说的那样 xff1a C 43 43 Primer 非常适合入门 这是事实 xff01 xff01
  • 用户态和内核态的转换 (转)

    1 xff09 用户态切换到内核态的3种方式 a 系统调用 这是用户态进程主动要求切换到内核态的一种方式 xff0c 用户态进程通过系统调用申请使用操作系统提供的服务程序完成工作 xff0c 比如前例中fork 实际上就是执行了一个创建新进
  • 嵌入式数字电路中的各种逻辑电平

    在通用的电子器件设备中 xff0c TTL和CMOS电路的应用非常广泛 但是面对现在系统日益复杂 xff0c 传输的数据量越来越大 xff0c 实时性要求越来越高 xff0c 传输距离越来越长的发展趋势 xff0c 掌握高速数据传输的逻辑电
  • 永久保存屏幕显示方向

    修改屏幕的显示方向 xff1a 在终端输入 xrandr o left 向左旋转90度 xrandr o right 向右旋转90度 xrandr o inverted 上下翻转 code code code xrandr o normal
  • RabbitMQ 与 Kafka深度解析(二)

    介绍 作为一名处理大量基于微服务的系统的软件架构师 xff0c 我经常会遇到一个反复出现的问题 xff1a 我应该使用RabbitMQ还是Kafka xff1f 出于某种原因 xff0c 许多开发人员认为这些技术是可以互换的 虽然在某些情况
  • 物联网时代25大开源IoT框架

    相当长一段时间以来 xff0c 互联网一直被用来连接人类并简化生活 xff0c 这是21世纪初的启示 今天 xff0c 我们将讨论各种物联网框架 现在 xff0c 我们正在进入一个基于互联网技术的新世界 xff0c 该世界不仅连接人 xff
  • 如何用maven使用低版本的jdk编译工程

    背景 xff1a 项目中自定义了一些二方库 xff0c 需要把一些工程编译成jar xff0c 给其他项目或者工程做为依赖引入 由于自己的项目使用的是JDK1 8 xff0c 而使用方是一个比较老的项目 xff0c 使用的是JDK 1 6
  • Docker 1.7.1版本pull私有镜像仓库报错,V1,V2等

    注意 xff1a 如下解决方案 xff0c 只能解决pull的问题 xff0c 不能解决push的问题 xff0c 方案请参考 xff1a 解决docker push问题 Docker 1 7版本和Docker CE的配置文件的位置是不同的
  • 解决docker push镜像时denied: requested access to the resource is denied : docker

    背景 xff1a 我用的是harbor管理镜像仓库 xff0c 之前没有上传下载过harbor上的镜像 在我配置了daemon json文件后 xff0c 可以pull镜像了 xff0c 但是我往library目录push的时候仍然有问题
  • Jenkins增加node节点

    setp 1 添加节点 setp 2 配置 1 Launch method 选择Launch slaver agents via SSH 2 填写主机ip 3 添加Credentiais xff0c 也就是主机的username和passw
  • Linux如何设置时区、时间

    查看时间命令 xff1a root span class hljs variable 64 123 span span class hljs symbol work test span span class hljs variable sp
  • centos如何查看linux内核,版本号等

    查看全部信息 xff1a zhangsan span class hljs variable 64 localhost span span class hljs variable span uname a span class hljs c
  • linux如何切换用户

    1 一般的用户增删改查 useradd test 执行后会在 home目录下添加test用户的目录 cat etc passwd 可以查看系统当前的用户 su test 切换用户 passwd test 给test用户创建密码 2 另类用户
  • 解决kubernetes启动容器时,容器一直是ContainerCreating不能running

    表象 kubectl f span class hljs operator span class hljs keyword create span redis yaml kubectl span class hljs keyword get
  • Eclipse创建的Maven项目报错Could not calculate build plan: Plugin

    1 错误描述 br Could not calculate build plan Plugin br org apache maven plugins maven resources plugin 2 5 or one of its dep
  • JAVA同一个类内方法调用AOP解决办法

    1 问题现象 64 Around 34 execution com unicom hl service TowerPayService processInsert 34 public Object around ProceedingJoin
  • Python多进程任务如何识别谁是谁

    在Python多进程 多线程编程中 xff0c 如果使用future和add done callback 经常会遇到如何区分异步任务的问题 这里推荐两种方式 方式一 xff1a 给future新增属性 def call back futur
  • spring如何将环境变量映射到JaveBean里

    spring 获取 xff0c 打印环境变量 public static void main String args Map lt String String gt env 61 System getenv Set lt Map Entry
  • ROS2 tf2广播器(broadcaster)、侦听器(listener)

    tf2介绍 安装依赖 span class token function sudo span span class token function apt get span span class token function install
  • 使用HttpParser类解析网页

    之前发过一篇文章 xff1a 利用String类制作简单的网络爬虫 http blog csdn net gfd54gd5f46 article details 54729874 这是是基于String类里的substring 方法对字符串