我有大约 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
本质上是搜索具有您指定的开始/结束的每一行的文本。
哎呀。我刚发现这个问题已经过时了。好吧,无论如何还是要回答这个问题。