通过Bash使用XMLStarlet将元素(<;td>;)插入HTML表的每一行
我想从链接列表中提取每个html表。我使用的代码如下所示:通过Bash使用XMLStarlet将元素(<;td>;)插入HTML表的每一行,bash,xpath,wget,xmlstarlet,xmllint,Bash,Xpath,Wget,Xmlstarlet,Xmllint,我想从链接列表中提取每个html表。我使用的代码如下所示: wget -O - "https://example.com/section-1/table-name/financial-data/" | xmllint --html --xpath '//*[@id="financial-data"]/div/table/tbody' - 2>/dev/null >> /Applications/parser/output.txt 但是,由于这不是我想要提取的唯一一个表,因此很
wget -O - "https://example.com/section-1/table-name/financial-data/" | xmllint --html --xpath '//*[@id="financial-data"]/div/table/tbody' - 2>/dev/null >> /Applications/parser/output.txt
但是,由于这不是我想要提取的唯一一个表,因此很难确定哪个财务数据属于哪个表,因此这一方法非常有效。在这种情况下,它将只解析附加到输出文件的一个表,其中SDTOUT如下所示:
<tbody>
<tr class="text-right">
<td class="text-left">Sep 08, 2017</td>
<td>4605.16</td>
<td>4661.00</td>
<td>4075.18</td>
<td>4228.75</td>
<td>2,700,890,000</td>
<td>76,220,200,000</td>
</tr>
<tr class="text-right">
<td class="text-left">Sep 07, 2017</td>
<td>4589.14</td>
<td>4655.04</td>
<td>4491.33</td>
<td>4599.88</td>
<td>1,844,620,000</td>
<td>75,945,000,000</td>
</tr>
...
</tbody>
wget -O - "https://example.com/section-1/table-name/financial-data/" |
xmllint --html --xpath '//*[@id="financial-data"]/div/table/tbody' - 2>/dev/null |
xmlstarlet ed --subnode "/tbody/tr" --type elem -n td -v "Hello World" >> /Applications/parser/output.txt
while IFS= read -r tbl; do
wget -O - "https://example.com/section-1/table-name/financial-data/" |
xmllint --html --xpath '//*[@id="financial-data"]/div/table/tbody' - 2>/dev/null |
sed 's#.*<tr.*#&\n <td>'"${tbl}"'</td>#' >> /Applications/parser/output.txt
done < alltables.txt
新更新 根据这一点,我遇到了这样一个脚本,它可以很容易地添加一个子节点:
<tbody>
<tr class="text-right">
<td class="text-left">Sep 08, 2017</td>
<td>4605.16</td>
<td>4661.00</td>
<td>4075.18</td>
<td>4228.75</td>
<td>2,700,890,000</td>
<td>76,220,200,000</td>
</tr>
<tr class="text-right">
<td class="text-left">Sep 07, 2017</td>
<td>4589.14</td>
<td>4655.04</td>
<td>4491.33</td>
<td>4599.88</td>
<td>1,844,620,000</td>
<td>75,945,000,000</td>
</tr>
...
</tbody>
wget -O - "https://example.com/section-1/table-name/financial-data/" |
xmllint --html --xpath '//*[@id="financial-data"]/div/table/tbody' - 2>/dev/null |
xmlstarlet ed --subnode "/tbody/tr" --type elem -n td -v "Hello World" >> /Applications/parser/output.txt
while IFS= read -r tbl; do
wget -O - "https://example.com/section-1/table-name/financial-data/" |
xmllint --html --xpath '//*[@id="financial-data"]/div/table/tbody' - 2>/dev/null |
sed 's#.*<tr.*#&\n <td>'"${tbl}"'</td>#' >> /Applications/parser/output.txt
done < alltables.txt
将以下内容写入标准输出:
<tbody>
<tr class="text-right">
<td class="text-left">Sep 08, 2017</td>
<td>4605.16</td>
<td>4661.00</td>
<td>4075.18</td>
<td>4228.75</td>
<td>2,700,890,000</td>
<td>76,220,200,000</td>
<td>Hello World</td>
</tr>
<tr class="text-right">
<td class="text-left">Sep 07, 2017</td>
<td>4589.14</td>
<td>4655.04</td>
<td>4491.33</td>
<td>4599.88</td>
<td>1,844,620,000</td>
<td>75,945,000,000</td>
<td>Hello World</td>
</tr>
...
</tbody>
在这里,您可以清楚地看到,我试图声明一个变量$header
,该变量应包括资产的名称。这不起作用,并使输出文件为空,可能是因为声明错误或管道的语法不正确
如何将相应的XPath(引用资产名称)插入新创建的子节点
?变量是我想到的第一件事;是否可以用其他方法完成?在将输出附加到output.txt
之前,应尝试插入附加列。确保所需的表名存储在变量中。你想做点什么
tbl=testtbl
echo "<tbody>
<tr class="text-right">
<td class="text-left">Sep 08, 2017</td>
<td>4605.16</td>
<td>4661.00</td>
<td>4075.18</td>
<td>4228.75</td>
<td>2,700,890,000</td>
<td>76,220,200,000</td>
</tr>
<tr class="text-right">
<td class="text-left">Sep 07, 2017</td>
<td>4589.14</td>
<td>4655.04</td>
<td>4491.33</td>
<td>4599.88</td>
<td>1,844,620,000</td>
<td>75,945,000,000</td>
</tr>
" | sed 's#.*<tr.*#&\n <td>'"${tbl}"'</td>#'
您可能可以在xmlstarlet中实现这一点,但我对xmlstarlet了解不够,无法给您一个简单的答案 另外,正如您所说,在将HTML传递给xmlstarlet
ed
之前,您必须通过xmllint或使用。它看起来不像ed
支持--html
我要做的是将xmlstarlet与XSLT样式表一起使用
这是非常冗长的,但它比尝试更安全。它也更容易扩展
这是XSLT。我添加了一些评论,试图帮助您了解正在发生的事情
XSLT1.0(stylesheet.xsl)
我可以通过在本地html文件上使用
cat
而不是wget
在本地测试这一点。如果您想让我将测试文件/结果添加到我的答案中,请告诉我。此脚本工作正常,但效率低下;它需要一些编辑:
name_query="html/body/div[3]/div/div[1]/div[3]/div[1]/h1/text()"
# Use xargs to TRIM result.
header=$(wget -O - "https://example.com/section-1/name-1/financial-data/" |
xmllint --html --xpath "$name_query" - 2>/dev/null |
xargs)
wget -O - "https://example.com/section-1/name-1/financial-data/" |
xmllint --html --xpath '//*[@id="financial-data"]/div/table/tbody' - 2>/dev/null |
xmlstarlet ed --subnode "/tbody/tr" --type elem -n td -v "$header" >> /Applications/parser/output.txt
这提出了两项要求:
$header
$header
<tbody>
<tr class="text-right">
<td class="text-left">Sep 08, 2017</td>
<td>4605.16</td>
<td>4661.00</td>
<td>4075.18</td>
<td>4228.75</td>
<td>2,700,890,000</td>
<td>76,220,200,000</td>
<td>Name 1</td>
</tr>
<tr class="text-right">
<td class="text-left">Sep 07, 2017</td>
<td>4589.14</td>
<td>4655.04</td>
<td>4491.33</td>
<td>4599.88</td>
<td>1,844,620,000</td>
<td>75,945,000,000</td>
<td>Name 1</td>
</tr>
...
</tbody>
2017年9月8日
4605.16
4661
4075.18
4228.75
2,700,890,000
76,220,200,000
名字1
2017年9月7日
4589.14
4655.04
4491.33
4599.88
1,844,620,000
75,945,000,000
名字1
...
这相对比较慢,因为实际上只能使用一个请求来完成,但我不知道怎么做。您正在重定向到
>/Applications/parser/output.txt
。重定向到>/Applications/parser/table name.txt
对您来说是一种解决方案吗?Hi@WalterA我不想更改文件本身的名称,相反,考虑到表被附加到名为output.txt的文件中,我想为该文件中的每个表添加某种标题,以便识别每个表。wget命令将把大约1160多个不同的表附加到一个文件中,其中只包含表信息,这就是为什么知道哪个表属于哪个数据集很方便的原因。我建议使用TABLE-NAME作为新行,如TABLE-NAME
。你能帮我吗?你能用xmlstarlet代替xmllint吗?嗨@DanielHaley我通过自制软件安装了xmlstarlet,所以我能用它代替。我正在看文档,我必须说我对这个有点陌生。你有什么想法?也许你可以提供一个答案;这对我真的很有帮助!根据,它说有一个命令-a
或-append
,但没有提供示例。我假设它可能类似于-d
或-I
。我是否必须首先解析出表,然后应用-a
命令将表名附加到每个
的末尾?我不介意在开头或结尾,只要每行都包含名称。另一方面,如何解析多个XPath?也就是说,一个XPath表示表,另一个表示同一网页中的名称。您好@WalterA谢谢您的回答:)我正在寻找一些更短、更简单的东西,比如xmlstarlet
。您熟悉它吗?您需要一个变量tbl
和一些循环用于所有解决方案。我不知道xmlstarlet
。例如,您知道如何将xmllint--html--xpath'/html/body/div[3]/div/div[1]/div[3]/div[1]/h1'
传递给变量吗?或者您是否建议通过命令-v
使用另一种方法?嗨@DanielHaley谢谢您的支持。我在我的问题中加入了我迄今为止的发现,这使我非常接近我的结果。您能否更新您的答案,说明如何进行更换?如果你能帮我完成这最后一步,我将很乐意接受你的解决方案!致以最良好的祝愿:)关于剧本有什么消息吗?你有改进的建议吗@丹尼尔哈利
name_query="html/body/div[3]/div/div[1]/div[3]/div[1]/h1/text()"
# Use xargs to TRIM result.
header=$(wget -O - "https://example.com/section-1/name-1/financial-data/" |
xmllint --html --xpath "$name_query" - 2>/dev/null |
xargs)
wget -O - "https://example.com/section-1/name-1/financial-data/" |
xmllint --html --xpath '//*[@id="financial-data"]/div/table/tbody' - 2>/dev/null |
xmlstarlet ed --subnode "/tbody/tr" --type elem -n td -v "$header" >> /Applications/parser/output.txt
<tbody>
<tr class="text-right">
<td class="text-left">Sep 08, 2017</td>
<td>4605.16</td>
<td>4661.00</td>
<td>4075.18</td>
<td>4228.75</td>
<td>2,700,890,000</td>
<td>76,220,200,000</td>
<td>Name 1</td>
</tr>
<tr class="text-right">
<td class="text-left">Sep 07, 2017</td>
<td>4589.14</td>
<td>4655.04</td>
<td>4491.33</td>
<td>4599.88</td>
<td>1,844,620,000</td>
<td>75,945,000,000</td>
<td>Name 1</td>
</tr>
...
</tbody>