尝试从每个包含 40 个表的 http 文件中提取两个表

尝试从每个包含 40 个表的 http 文件中提取两个表

我有大约 20 个网页。每个页面都有顶部横幅导航,然后包含最多 20 辆车的信息。每辆车有 2 个表格。
逻辑流程是:页面导航,表格 1 对应车辆 1,表格 2 对应车辆 1,表格 1 对应车辆 2,表格 2 对应车辆 2,...页面结束。
下面包含表格示例。

我想将信息从 html 页面中提取出来并存入数据库。
计划:将每辆车的数据分离到单独的文件中,然后从文件中解析/提取数据。

我不懂 awk 所以我使用 sed。

提取计划:找到包含“car_photo”的行,返回 4 行(这将是表格标签),从该行提取直到第二个 /table 标签。重复直到最后一组表格。

我在网上查找了如何让 sed 从给定的行号提取直到正则表达式的下一个实例的示例...它一直提取直到最后一个实例。&即使它确实有效,我也希望它提取到第 2 个实例。

这是一个文件的示例,其中的数据被更通用的信息所替换。


32321 品牌: 型号:
年份:
VIN:
颜色:
购置年份:
里程: 上次换油: 保险到期: 注册到期:
32322 品牌: 型号:
年份:
VIN:
颜色:
购置年份:
里程: 上次换油: 保险到期: 注册到期:
32321 品牌: 型号:
年份:
VIN:
颜色:
购置年份:
里程: 上次换油: 保险到期: 注册到期:
32323 品牌: 型号:
年份:
VIN:
颜色:
购置年份:
里程: 上次换油: 保险到期: 注册到期:
32324 品牌: 型号:
年份:
VIN:
颜色:
购置年份:
里程: 上次换油: 保险到期: 注册到期:
32325 品牌: 型号:
年份:
VIN:
颜色:
购置年份:
里程: 上次换油: 保险到期: 注册到期:


我尝试创建一个运行 20 次的循环。每次,sed 都会提取第 1 行到带有 的行,</table> 然后 sed 再次运行以删除这些行。然后,它再次提取第 1 行到下一行</table>(以获取第二个表), sed然后删除第二个表。

Each time `sed` extracts a table, it concatenates to a new file using the loop counter.

问题是sed不会在 第一次出现时停止</table>。它会在 最后一次出现时停止。

答案1

如果我经常这样做,我会使用类似 Ruby 的 Nokogiri gem 进行 XPath 解析。

但是,这里有一些可以工作的方法,但如果没有 bash 脚本来组合它们,每个文件就需要几个步骤(我猜在你的情况下是 20 个)。

步骤1:将html尽量转换成逐行的形式,以便awk能够处理。

从你的评论的 html 输入开始car.html,我做了

cat car.html | awk -F"> " '{ for( i = 1; i <= NF; i++ ) printf( "%s>\n", $i ) } ' > new.html

这给了我一个new.html类似的文件

<table>
<tr><td width="90">
<div class="car_photo">
<div class="space">
<img src="../photos/veh5.jpeg">
</div>
</div>
</div>
</td>
<td align="right" class="car_details" width="400">
<table>
<tr>
<td class="line_bottom" width="190">
<div class="text_left">32325</a>
</div>
</td>
</tr>
</table>
<div class="line_bottom">
Make: </div>
<div class="line_bottom">Model: <br>Year: <br />
</div>
</td>
<td class="car_details" width="400">
<div class="line_bottom">Mileage:</div>
<div class="line_bottom">Oil Change: </div>
<div class="line_bottom">Registration:</div>
<br>
</td>
</tr>
</table>

步骤 2:获取该文件并将其放入我放入其自己的文件中的 awk 脚本中awko

#!/usr/bin/awk -f

BEGIN { FS=">" }

$1 ~ /<table/ { table_cnt++ }

$1 ~ /<\/table/ { table_cnt-- }

table_cnt > 0 {
    for( i = 1; i <= NF; i++ ) {
        split( $i, arr, "<" )
        if( length( arr[ i ] ) > 0 )
            printf( "%s\n", arr[ 1 ] )
    }

}

像这样运行

awko new.html 

给了我如下结果:

32325
Make: 
Model: 
Mileage:
Oil Change: 
Registration:

可以修改输出,awko改为使用 CSV 样式的输出,以便更轻松地导入数据库。同样,这些不同的步骤可以组合在 shell 脚本中,以便在适当的循环中完成“繁重的文件名提升”,但我现在没时间这样做。

awko本质上是搜索具有您指定的开始/结束的每一行的文本。

哎呀。我刚发现这个问题已经过时了。好吧,无论如何还是要回答这个问题。

相关内容