Mojo::DOM - 如何从 dom 对象中解析数据集?
Posted
技术标签:
【中文标题】Mojo::DOM - 如何从 dom 对象中解析数据集?【英文标题】:Mojo::DOM - How to parse sets of data out of a dom object? 【发布时间】:2021-06-23 18:53:32 【问题描述】:我在 html 结果页面中有数据,我想迭代地解析出其中的数据集。在一般的“结果页”格式中,有一个主要的结果部分(div),其中包含一堆子部分(sub divs),这些子部分又包含带有结果数据的各种标签。
Faux, pseudo, not-real code
$file = Mojo::File->new('BigData.htm'); # Read in some file
$dom = Mojo::DOM->new($file->slurp); # Slurp the dom out of it
#
$rs = $dom->at('div.resultsSection'); # Find the beginning of the results section
#
for my $ss ($rs->at('div.subSection') # Start looping through the subsections
#
$cs = $ss->find('p.coolStuff'); # Find correlating data
$is = $ss->find('div.importantStuff'); #
#
if(! defined $is) # Make decisions based on data availability
$is = $ss->find('div.differentClass'); # and data quality
#
push (@array, "$cs\t$is\n"); # Reformat it for my purposes
#
显然,上面的虚假、伪、非真实代码在任何意义上都是完全虚假的,除了以下内容: 这是我正在尝试做的事情的逻辑表示。 "->at()" 应该返回一个 dom 对象,该对象以第一次出现的给定标签开始。 “->find()”返回匹配标签的集合。我理解使用 css 选择器(和其他方法)我可以将两种方法的结果限制为唯一的项目(我确实这样做了)。但是,我的知识到此为止。
我能够一次找到一种类型的所有标签。但数据很复杂,事后无法关联结果。
我还能够抓取一个小节,并收集我需要的数据集,但我不知道如何创建一个遍历所有小节的循环。
这一切都错了吗?
【问题讨论】:
【参考方案1】:我想出了一个可行的解决方案。我不知道这是否是最好的解决方案,但它直截了当且简单,这肯定是正确的方向。
下面的 html 段以主“容器”开头,并包含一个搜索结果行:(我应该将其包含在我原来的问题中 - 抱歉)
<div class="container">
<div class="row searchResultRow">
<div class="col-sm-12">
<div class="row">
<div class="col-md-12">
<p class="searchResultTitle">Some Data Here</p>
</div>
</div>
<div class="row">
<div class="col-sm-7 col-md-8">
<div class="row">
<div class="col-md-2">
<div class="clearfix"> <img class="searchResultImg" src='/images/image.png' /> </div>
<p> <a class="bodyLink" href="description.html">View Details</a> </p>
</div>
<div class="col-sm-5 col-md-4">
<p> <span class="gridTxtLbl br-responsive-sm">Type</span> <span class="gridDataItem br-responsive-sm">Organic</span> </p>
</div>
<div class="col-sm-3 col-md-3">
<p> <span class="gridTxtLbl br-responsive-sm">Year</span> <span class="gridDataItem br-responsive-sm">1955</span> </p>
</div>
<div class="col-sm-4 col-md-3"> </div>
</div>
<div class="row">
<div class="col-md-12"> </div>
</div>
</div>
<div class="col-sm-5 col-md-4">
<p class="gridTxtLbl">Origin</p>
<div class="">
<div class="mapIconDiv">
<a href="/Maps/ShowMap" id="res_thx-1138">
<span class="iconWithText">
<span class="fa fa-home" aria-hidden="true"></span>
<br />Map
</span>
</a>
<script>
$(function()
$('#res_' + thx-1138).click(function(e)
e.preventDefault();
var url = $(this).attr('href');
$.ajax(
url: url,
success: function(html)
$('#mapModal').html(html);
$('#mapModal').modal();
initialize(40.7856211, -76.5780298, 'Secret Location<br/>Lincoln County, NV', '2');
);
);
);
</script>
</div>
<div class="searchResultAddress">
<br />Lincoln County, NV</div>
</div>
</div>
</div>
</div>
</div>
下面的代码循环遍历数据并抓取什么:
use Mojo::UserAgent;
use Mojo::File;
use feature 'say';
$infile = 'searchResults.htm';
unless( -e $infile ) # Did I already save this data?
$ua = Mojo::UserAgent->new; # No? Then go get it
$tx = $ua->get( 'https://www.someurl.com/BigDataResults.html' ); # URL hardcoded here to simplify this post
unless( $tx->result->is_success )
die "Doh!!! ", $tx->result->code
$tx->result->save_to( $searchResults.htm );
$data = Mojo::File->new( $infile )->slurp;
$dom = Mojo::DOM->new( $data );
$c = $dom->at('div.container'); # Return the dom from the beginning of the results data section
# in my case, this "div.class" is unique
for $row ($c->find('div.searchResultRow')->compact->each) # Return a collection of each subsection (row)
#
$data1 = $row->at('div > div > div > div > p')->text; # Use css direct child selectors to navigate paths into nested tag structures
$data2 = $row->at('div > div > div > div > div > div > script')->text; # <-- There was some lat/long data in this script I needed to parse out
$data3 = $row->at('div > div > div > p > span')->text; # <-- More data in another nested tag structure
#
# A Lot of massaging and formatting code was here #
push (@array, "$cs\t$is\n"); # wrap up the data for later
这是运行的实际代码,尽管我摆脱了所有使主逻辑混乱的东西。
给其他试图找到此问题答案的人的说明:
虽然直接子选择器“>”类似于硬编码路径,因此是一个脆弱的解决方案,但对我而言,它的优势在于长 css 选择器路径是唯一的。【讨论】:
以上是关于Mojo::DOM - 如何从 dom 对象中解析数据集?的主要内容,如果未能解决你的问题,请参考以下文章