bash中的xpath解析表

bash中的xpath解析表,bash,csv,xpath,xmllint,Bash,Csv,Xpath,Xmllint,我有一个html表,我想用bash解析它 (注意:我使用了R来实现这一点,但我想尝试在bash中轻松地与另一个shell脚本集成) 可从以下url获取该表: 通过查看源代码-特定表的xpath参考是: //*[@id="ctl03_DesktopThreePanes1_ThreePanes_ctl01_MDlisting"] 如何直接从bash将该表解析为csv文件 我尝试了以下方法: curl "http://faostat.fao.org/site/384/default.aspx" |

我有一个html表,我想用bash解析它 (注意:我使用了R来实现这一点,但我想尝试在bash中轻松地与另一个shell脚本集成)

可从以下url获取该表:

通过查看源代码-特定表的xpath参考是:

//*[@id="ctl03_DesktopThreePanes1_ThreePanes_ctl01_MDlisting"]
如何直接从bash将该表解析为csv文件

我尝试了以下方法:

curl "http://faostat.fao.org/site/384/default.aspx" | xpath '//*[@id="ctl03_DesktopThreePanes1_ThreePanes_ctl01_MDlisting"]' > test.txt
这只返回test.txt的空白文本

有人能帮我在bash中使用xpath解析出有效的html表并创建一个CSV文件吗

感谢您的帮助。

/*[@id=“ctl03\u DesktopThreePanes1\u ThreePanes\u ctl01\u MDlisting”]/tr
(也就是说,将
/tr
附加到您问题中的XPath表达式后)将只获取每一行,并跳过
包装器(您不需要在输出中对其做任何操作)

然后,您还需要通过
sed
perl
或其他方式来传递
xmllint--xpath
输出:

示例:perl版本
wget -q -O - "http://faostat.fao.org/site/384/default.aspx" \
   | xmllint --html \
     --xpath '//*[@id="ctl03_DesktopThreePanes1_ThreePanes_ctl01_MDlisting"]/*' - \
     2>/dev/null \
   | perl -pe 's/<tr[^>]+>//' \
   | perl -pe 's/<\/tr>//' \
   | perl -pe 's/^\s+<t[dh][^>]*>//' \
   | perl -pe 's/<\/t[dh]><t[dh][^>]*>/|/g' \
   | perl -pe 's/<\/t[dh]>//' \
   | grep -v '^\s*$'
wget -q -O - "http://faostat.fao.org/site/384/default.aspx" \
   | xmllint --html \
     --xpath '//*[@id="ctl03_DesktopThreePanes1_ThreePanes_ctl01_MDlisting"]/*' - \
     2>/dev/null \
   | sed -E 's/<tr[^>]+>//' \
   | sed -E 's/<\/tr>//' \
   | sed -E 's/^[[:space:]]+<t[dh][^>]*>//' \
   | sed -E 's/<\/t[dh]><t[dh][^>]*>/|/g' \
   | sed -E 's/<\/t[dh]>//' \
   | grep -v '^\s*$'

使用
colrm
命令格式化输出 如果希望在控制台中读取结果的打印/格式化列/表视图并滚动/翻页,请将输出进一步导入
colrm
命令,如下所示:

wget -q -O - "http://faostat.fao.org/site/384/default.aspx" \
   | xmllint --html \
     --xpath '//*[@id="ctl03_DesktopThreePanes1_ThreePanes_ctl01_MDlisting"]/*' - \
     2>/dev/null \
   | sed -E 's/<tr[^>]+>//' \
   | sed -E 's/<\/tr>//' \
   | sed -E 's/^[[:space:]]+<t[dh][^>]*>//' \
   | sed -E 's/<\/t[dh]><t[dh][^>]*>/|/g' \
   | sed -E 's/<\/t[dh]>//' \
   | grep -v '^\s*$' \
   | column -t -s '|' \
   | colrm 14 21 | colrm 20 28 | colrm 63 95 | colrm 80
或者,您可以使用
cut
命令而不是
colrm
来获得相同的格式


如何生成真正的CSV 如果您确实想要真正的CSV,而不是像上面那样漂亮的打印/格式化输出,那么您还必须在字段周围发出引号,并在字段内转义CSV现有引号;像这样:

wget -q -O - "http://faostat.fao.org/site/384/default.aspx" \
   | xmllint --html \
     --xpath '//*[@id="ctl03_DesktopThreePanes1_ThreePanes_ctl01_MDlisting"]/*' - \
     2>/dev/null \
   | sed -E 's/<tr[^>]+>//' \
   | sed -E 's/<\/tr>//' \
   | sed -E 's/^[[:space:]]+<t[dh][^>]*>//' \
   | sed -E 's/<\/t[dh]><t[dh][^>]*>/|/g' \
   | sed -E 's/<\/t[dh]>//' \
   | grep -v '^\s*$' \
   | column -t -s '|' \
   | colrm 14 21 | colrm 20 28 | colrm 63 95 | colrm 80
示例:真实CSV输出
wget -q -O - "http://faostat.fao.org/site/384/default.aspx" \
   | xmllint --html \
     --xpath '//*[@id="ctl03_DesktopThreePanes1_ThreePanes_ctl01_MDlisting"]/tr' - \
   | sed -E 's/"/""/g' \ 
   | sed -E 's/<tr[^>]+>//' \
   | sed -E 's/<\/tr>//' \
   | sed -E 's/^[[:space:]]+<t[dh][^>]*>/"/' \
   | sed -E 's/<\/t[dh]><t[dh][^>]*>/","/g' \
   | sed -E 's/<\/t[dh]>/"/' \
   | grep -v '^\s*$'
因此,上面代码片段的
sed-E的/“/”“/g”
部分就是这样做的

上述示例的CSV输出
"Group Name","Item FAO Code","Item HS+ Code","Item Name ","Definition"
"Crops","800","5304_c","Agave fibres nes","Including inter alia: Haiti hemp…"
"Crops","221","0802.11_a","Almonds, with shell","Prunus amygdalus; P. communis…"
"Crops","711","0909","Anise, badian, fennel, coriander","Include: anise…"

免责声明:您应该避免对HTML/XML进行基于regexp的处理 (强制性免责声明)综上所述,许多人会告诉你基于regexp的HTML/XML处理很难处理,而且很容易出错,所以请谨慎使用上述方法(如果有的话)

如果您有时间做对了,那么您应该做的是:而不是使用一个好的Web抓取库,或者使用Python+
lxml
来实际处理计算XPath表达式返回的结果(而不是字符串化结果),或者使用
xsltproc
或其他一些XSLT引擎

Group Name         Item FAO Code    Item HS+ Code    Item Name      Definition
Crops              800              5304_c           Agave fib      Including int
Crops              221              0802.11_a        Almonds,       Prunus amygda
Crops              711              0909             Anise, ba      Include: anis
Crops              515              0808.10_a        Apples         Malus pumila;
Crops              526              0809.10_a        Apricots       Prunus armeni
…
但是,您只需要从命令行中获得一些快速、干净的东西,上面的工作就可以完成了。
但是,它很脆弱,因此如果输出的某些部分以某种意外的方式被破坏,请不要感到震惊。如果您希望HTML/XML具有健壮性,请不要使用基于regexp的方法。

我设法做到了以下几点:
wget-q-O-http://faostat.fao.org/site/384/default.aspx“| xmllint--html--xpath'/*[@id=”ctl03_DesktopThreePanes1_ThreePanes_ctl01_MDlisting“]'-2>/dev/null>test.txt
但这不会提供CSV输出。有什么办法吗?
"Group Name","Item FAO Code","Item HS+ Code","Item Name ","Definition"
"Crops","800","5304_c","Agave fibres nes","Including inter alia: Haiti hemp…"
"Crops","221","0802.11_a","Almonds, with shell","Prunus amygdalus; P. communis…"
"Crops","711","0909","Anise, badian, fennel, coriander","Include: anise…"