老程序员谈编程

html源代码提取分析利器htmlq

以前的笨办法:

https://developers.redhat.com/articles/2022/10/05/filter-content-html-using-regular-expressions-grep#

项目地址 :https://github.com/mgdm/htmlq/releases

$ htmlq --help
htmlq 0.4.0
Michael Maclean <michael@mgdm.net>
Runs CSS selectors on HTML

USAGE:
    htmlq [FLAGS] [OPTIONS] [--] [selector]...

FLAGS:
    -B, --detect-base          Try to detect the base URL from the <base> tag in the document. If not found, default to
                               the value of --base, if supplied
    -h, --help                 Prints help information
    -w, --ignore-whitespace    When printing text nodes, ignore those that consist entirely of whitespace
    -p, --pretty               格式化输出漂亮Pretty-print the serialised output
    -t, --text                 纯文本Output only the contents of text nodes inside selected elements
    -V, --version              Prints version information

OPTIONS:
    -a, --attribute <attribute>         返回标签的属性值Only return this attribute (if present) from selected elements
    -b, --base <base>                   Use this URL as the base for links
    -f, --filename <FILE>               指定输入文件The input file. Defaults to stdin
    -o, --output <FILE>                 The output file. Defaults to stdout
    -r, --remove-nodes <SELECTOR>...    删除指定的选择器Remove nodes matching this expression before output. May be specified multiple
                                        times

ARGS:
    <selector>...    The CSS expression to select [default: html]

安装可根据官网。以下是经典例子:

以这个html文件为例:

<html>
    <head> <title>Sample HTML</title> </head>
    <body>
        <p>Fantasy books:</p>
        <li>Harry Potter</li>
        <li>Cradle</li>
        <li>The Stormlight Archive</li>
        <a href="https://moneyslow.com/">blog link</a>
    </body>
</html>
只打印文本:
$ htmlq -w --text -f sample.html
Sample HTML
Fantasy books:
Harry Potter
Cradle
The Stormlight Archive
blog link

获取元素对值:,比如li标签
$ htmlq 'li' -f sample.html
<li>Harry Potter</li>
<li>Cradle</li>
<li>The Stormlight Archive</li>

纯文本,加--text:
$ htmlq --text 'li' -f sample.html
Harry Potter
Cradle
The Stormlight Archive

利用-a参数获取属性,下面例子意思是获取a标签的href属性的值:
$ htmlq -a href 'a' -f sample.html
https://moneyslow.com/

扩展阅读

1、CSS ID选择器,用符号:#

curl --silent https://www.rust-lang.org/ | htmlq '#get-help'

2、CSS属性选择器,–attribute参数提取href值,如果你提取/查找HTML页面的元素的属性值,可以为htmlq指定--attribute选项,然后指定HTML元素的名称和该元素属性名称。例如搜索/提取HTML页面所有a元素href属性。你将运行以下命令:

curl --silent https://www.rust-lang.org/ | htmlq --attribute href a

这将会输出所有html页面中所有a元素的href属性,即页面中所有可跳转的链接。内容类似于下面的输出:

3、使用CSS class类名选择器提取文本, 一个点后面跟class类标签

# htmlq '.header-publisher-wrapper' -f 9896.html 
<div class="header-publisher-wrapper" style="flex-shrink:0">
                        <div aria-expanded="false" aria-haspopup="true" aria-label="发布作品" class="ttp-header-publisher" role="button" tabindex="0"><a class="publisher-icon" rel="nofollow">发布</a></div>
                    </div>

输出内容将不包含HTML的元素标签,仅剩下文本

4、在输出之前移除指定节点,如果需要在你提取的数据或者截取的HTML片段移除不需要的元素,可以为htmlq命令指定--remove-nodes选项。该选项在一个CSS选择器之后,并在该选项之后添加要删除节点的CSS选择器。例如要从.whynix类名选择器中移除所有svg元素/节点,你将运行以下命令:

curl --silent https://nixos.org/ | ./target/debug/htmlq '.whynix' --remove-nodes svg
具体例子:
# htmlq '.channel-wrapper' -f 9896.html 
<div class="channel-wrapper">
                        <div class="ttp-channel-nav">
                            <ul class="ttp-channel-default-nav">
                                <li aria-label="关注频道" role="button" tabindex="0">
                                    <div class="ttp-channel-default-nav-item">关注</div>
                                </li>
                                <li aria-label="推荐频道" role="button" tabindex="0">
                                    <div class="ttp-channel-default-nav-item">推荐</div>
                                </li>
                                <li aria-label="廊坊频道" role="button" tabindex="0">
                                    <div class="ttp-channel-default-nav-item">
                                        <div class="ttp-city-selector-wrapper">
                                            <div class="ttp-city-selector"><span class="ttp-city-selector-current-name">廊坊</span><button aria-label="切换城市" aria-pressed="false" class="ttp-city-selector-city-picker" type="button"></button></div>
                                        </div>
                                    </div>
                                </li>
                                <li aria-label="视频频道" role="button" tabindex="0">
                                    <div class="ttp-channel-default-nav-item">视频</div>
                                </li>
                                <li aria-label="财经频道" role="button" tabindex="0">
                                    <div class="ttp-channel-default-nav-item">财经</div>
                                </li>
                                <li aria-label="科技频道" role="button" tabindex="0">
                                    <div class="ttp-channel-default-nav-item">科技</div>
                                </li>
                                <li aria-label="热点频道" role="button" tabindex="0">
                                    <div class="ttp-channel-default-nav-item">热点</div>
                                </li>
                                <li aria-label="国际频道" role="button" tabindex="0">
                                    <div class="ttp-channel-default-nav-item">国际</div>
                                </li>
                                <li aria-expanded="false" aria-haspopup="true" aria-label="更多频道" class="more-btn-wrapper" role="button" tabindex="0">
                                    <div class="more-btn">更多</div>
                                    <div class="ttp-channel-more-nav-wrapper ttp-popup-container popup-anime-hide popup-hide" style="transform: translateX(-50%) scale(0.8); transform-origin: center top;">
                                        <ul class="ttp-channel-more-nav" role="menu">
                                            <li aria-label="军事频道" role="menuitem" tabindex="-1">
                                                <div class="ttp-channel-more-nav-item">军事</div>
                                            </li>
                                            <li aria-label="体育频道" role="menuitem" tabindex="-1">
                                                <div class="ttp-channel-more-nav-item">体育</div>
                                            </li>
                                            <li aria-label="娱乐频道" role="menuitem" tabindex="-1">
                                                <div class="ttp-channel-more-nav-item">娱乐</div>
                                            </li>
                                            <li aria-label="历史频道" role="menuitem" tabindex="-1">
                                                <div class="ttp-channel-more-nav-item">历史</div>
                                            </li>
                                            <li aria-label="美食频道" role="menuitem" tabindex="-1">
                                                <div class="ttp-channel-more-nav-item">美食</div>
                                            </li>
                                            <li aria-label="直播频道" role="menuitem" tabindex="-1">
                                                <div class="ttp-channel-more-nav-item"><a aria-hidden="true" href="https://live.ixigua.com" rel="noopener nofollow noreferrer" tabindex="-1" target="_blank">直播</a></div>
                                            </li>
                                            <li aria-label="旅游频道" role="menuitem" tabindex="-1">
                                                <div class="ttp-channel-more-nav-item">旅游</div>
                                            </li>
                                            <li aria-label="懂车帝频道" role="menuitem" tabindex="-1">
                                                <div class="ttp-channel-more-nav-item"><a aria-hidden="true" href="https://www.dongchedi.com/?zt=tt_pc_home_channel" rel="noopener nofollow noreferrer" tabindex="-1" target="_blank">懂车帝</a></div>
                                            </li>
                                        </ul>
                                    </div>
                                </li>
                            </ul>
                        </div>
                    </div>

想要去掉 li 标签对,睁大眼睛看好了:

# htmlq '.channel-wrapper' --remove-nodes li -f 9896.html 
<div class="channel-wrapper">
                        <div class="ttp-channel-nav">
                            <ul class="ttp-channel-default-nav">
                                
                                
                                
                                
                                
                                
                                
                                
                                
                            </ul>
                        </div>
                    </div>
总结:li标签对中的所有数据(蓝色的脚本)都被删除!

5、格式化HTML输出,htmq除了提取HTML页面的数据,元素,属性,片段之外还可以对HTML片段进行格式化输出,例如以下命令将格式化输出选择器#posts元素片段的输出,你将运行以下命令:

curl --silent https://mgdm.net | htmlq --pretty '#posts'

6、HTML语法高亮

bat命令是一个语法高亮的命令。可在终端中高亮几乎所有语言的语法和关键词。让你更容易查看数据与语法。htmlq命令的结果是写到标准输出,这允许我们将htmlq命令的结果通过管道传递给bat命令高亮HTML片段关键词/语法/属性等。

例如我们使用htmlq提取body元素所有内容,包括HTML标签,属性。即不只是文本,并通过bat命令高亮HTML语法你将运行以下命令:

curl --silent example.com | htmlq 'body' | bat --language html