微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

Mojo::DOM - 如何从 dom 对象中解析数据集?

如何解决Mojo::DOM - 如何从 dom 对象中解析数据集?

我在 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 选择器(和其他方法)我可以将两种方法的结果限制为唯一的项目(我确实这样做了)。然而,我的知识就止步于此。

我可以一次找到一种类型的所有标签。但数据复杂,事后无法关联结果。

我也可以抓取单个小节,并收集我需要的数据集,但我不知道如何创建遍历所有小节的循环。

我的意思是不是全错了?

解决方法

我想出了一个有效的解决方案。我不知道这是否是最好的解决方案,但它直接而简单,这当然是正确的方向。

下面的 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 alt="clearfixalt" 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 选择器路径是唯一的。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。