如何使用xmllint结合XPath正确提取HTML中属性的纯值
如何使用xmllint结合XPath正确提取HTML中属性的纯值
我完全懂你遇到的坑——用//a/@href查出来的结果带着href=和引号,而套个string()又只返回第一个匹配的链接,明明知道有50个结果却只能拿到一个,确实挺闹心的。
先给你解释下原因:
//a/@href返回的是所有匹配的属性节点,xmllint默认会把这些节点序列化成XML格式,也就是href="xxx"这种形式,所以你看到的是带属性名的完整内容。- 而
string(//a/@href)只返回第一个结果,是因为XPath 1.0里string()函数接收节点集时,只会取节点集里的第一个节点的字符串值,自然只能拿到第一个链接。
下面给你两个实用的解决办法:
方法一:结合文本处理工具快速提取纯值
这是最常用的方案,用sed或者awk把多余的部分去掉就行,执行命令如下:
xmllint --html --xpath '//a/@href' <(curl -L www.html-tidy.org) | sed 's/^href="//;s/"$//'
或者用awk按引号分割取值:
xmllint --html --xpath '//a/@href' <(curl -L www.html-tidy.org) | awk -F'"' '{print $2}'
这时候再用wc统计,就能得到和原来一致的50个结果了,每一行都是纯链接地址。
方法二:纯xmllint的shell模式方案
如果你不想依赖外部工具,可以用xmllint的交互式shell模式来逐个输出属性值:
xmllint --html --shell <(curl -L www.html-tidy.org) << EOF | grep -E '^ href="' | sed 's/^ href="//;s/"$//' xpath //a/@href quit EOF
这个命令会先进入xmllint的shell,执行XPath查询后退出,再通过grep过滤出属性行,最后用sed提取纯值。
两种方法都能解决你的问题,第一种更简洁高效,日常用得最多。
备注:内容来源于stack exchange,提问作者00M
相关产品推荐
相关产品推荐

