gpt4 book ai didi

带有条件的 Perl XPath 语句 - 这可能吗?

转载 作者:行者123 更新时间:2023-12-03 15:35:21 26 4
gpt4 key购买 nike

这个问题已经改写了。我正在使用 CPAN Perl 模块 WWW::Mechanize浏览网站,HTML::TreeBuilder-XPath捕获内容和xacobeo在 HTML/XML 上测试我的 XPath 代码。目标是从基于 PHP 的网站调用这个 Perl 脚本,并将抓取的内容上传到数据库中。因此,如果内容“缺失”,仍然需要考虑。

下面是一个经过测试的简化示例代码,描述了我的挑战。笔记:

  • 此页面是动态填充的,包含各种 ITEMS为不同的商店输出;不同数量的Products*每个商店都会存在。这些产品列表下面可能有也可能没有明细表。
  • 捕获的数据必须在数组中,并且必须维护任何逐项列表(如果存在)与产品列表的关联。

  • 下面,每个商店的示例 xml 更改(如上所述),但为简洁起见,我只显示一种“类型”的输出。我意识到可以将所有数据捕获到一个数组中,然后使用正则表达式来破译内容,以便将其上传到数据库中。我正在寻求更好的 XPath 知识来帮助简化这个(和 future 的)解决方案。
    <!DOCTYPE XHTML>
    <table id="8jd9c_ITEMS">
    <tr><th style="color:red">The Products we have in stock!</th></tr>

    <tr><td><span id="Product_NUTS">We have nuts!</span></td></tr>
    <tr><td>
    <!--Table may or may not exist -->
    <table>
    <tr><td style="color:blue;text-indent:10px">Almonds</td></tr>
    <tr><td style="color:blue;text-indent:10px">Cashews</td></tr>
    <tr></tr>
    </table>
    </td></tr>

    <tr><td><span id="Product_VEGGIES">We have veggies!</span></td></tr>
    <tr><td>
    <!--Table may or may not exist -->
    <table>
    <tr><td style="color:blue;text-indent:10px">Carrots</td></tr>
    <tr><td style="color:blue;text-indent:10px">Celery</td></tr>
    <tr></tr>
    </table>
    </td></tr>

    <tr><td><span id="Product_ALCOHOL">We have booze!</span></td></tr>
    <!--In this case, the table does not exist -->
    </table>

    一个 XPath 语句:
    '//table[contains(@id, "ITEMS")]/tr[position() >1]/td/span/text()'

    会发现:
    We have nuts!
    we have veggies!
    We have booze!

    和一个 XPath 语句:
    '//table[contains(@id, "ITEMS")]/tr[position() >1]/td/table/tr/td/text()'

    会发现:
    Almonds
    Cashews
    Carrots
    Celery

    可以组合这两个 XPath 语句:
    '//table[contains(@id, "ITEMS")]/tr[position() >1]/td/span/text() | //table[contains(@id, "ITEMS")]/tr[position() >1]/table/tr/td/text()'

    要查找:
    We have nuts!
    Almonds
    Cashews
    We have veggies!
    Carrots
    Celery
    We have booze!

    同样,可以使用正则表达式对上面的数组进行解密(在实际代码中),因为它是产品到列表的关联。 但是可以使用 XPath 以保持这种关联的方式构建数组吗?

    例如(伪说话,这不起作用):
    '//table[contains(@id, "ITEMS")]/tr[position()>1]/td/span/text() | 
    if exists('//table[contains(@id, "ITEMS")]/tr[position() >1]/table))
    then ("NoTable") else ("TableRef") |
    Save this result into @TableRef ('//table[contains(@id, "ITEMS")]/tr[position() >1]/table/tr/td/text()')'

    在 Perl 中构建多维数组(传统意义上的)是不可能的,参见 perldoc perlref但希望类似于上述的解决方案可以创建如下内容:
    @ITEMS[0] => We have nuts!
    @ITEMS[1] => nutsREF <-- say, the last word of the span value + REF
    @ITEMS[2] => We have veggies!
    @ITEMS[3] => veggiesREF <-- say, the last word of the span value + REF
    @ITEMS[4] => We have booze!
    @ITEMS[5] => NoTable <-- value accounts for the missing info

    @nutsREF[0] => Almonds
    @nutsREF[1] => Cashews

    @veggiesREF[0] => Carrots
    @veggiesREF[1] => Celery

    在实际代码中,产品是已知的,所以 my @veggiesREFmy @nutsREF可以在 XPath 输出的预期中定义。

    我意识到 XPath if/else/then 功能在 XPath 2.0 版本中。我在 ubuntu 系统上并在本地工作,但我仍然不清楚我的 apache2 服务器使用的是它还是 1.0 版本。我该如何检查?

    最后,如果您可以展示如何从 PHP 表单提交调用 Perl 脚本以及如何将 Perl 数组传回给调用 PHP 函数,那么这将有助于获得赏金。 :)

    谢谢!

    最后编辑:

    该帖子下方的评论直接指向了一个过于模糊的初始帖子。随后的重新发布(和赏金)得到了 ikegami 的回应,它非常有创意地使用它解决了伪问题,但事实证明我很难在我的实际应用程序中掌握和重用 - 这需要在各种 html 页面上进行多次使用。在我们对话的第 18 条评论中,我终于发现了他对 ($cat) 的含义和用法——他使用的一种未记录的 Perl 语法。对于新读者来说,理解这种语法可以理解(和重新格式化)他对问题的智能解决方案。他的帖子当然符合 OP 中寻求的基本要求,但没有使用 HTML::TreeBuilder::XPath 来完成。

    jpalecek 使用 HTML::TreeBuilder::XPath,但不会将捕获的数据放入数组中,以便传回 PHP 函数并上传到数据库。

    我从两位响应者那里学到了东西,希望这篇文章能帮助像我这样的 Perl 新手。任何最终贡献将不胜感激。

    最佳答案

    如果我猜测,您的问题是:“我如何从提供的输入中获得以下信息?”

    my $categorized_items = {
    'We have nuts!' => [ 'Almonds', 'Cashwes' ],
    'We have veggies!' => [ 'Carrots', 'Celery' ],
    'We have booze!' => [ ],
    };

    如果是这样,我会这样做:
    use Data::Dumper qw( Dumper );
    use XML::LibXML qw( );

    my $root = XML::LibXML->load_xml(IO=>\*DATA)->documentElement;

    my %cat_items;
    for my $cat_tr ($root->findnodes('//table[contains(@id, "ITEMS")]/tr[td/span]')) {
    my ($cat) = map $_->textContent(),
    $cat_tr->findnodes('td/span');

    my @items = map $_->textContent(),
    $cat_tr->findnodes('following-sibling::tr[position()=1]/td/table/tr/td');

    $cat_items{$cat} = \@items;
    }

    print(Dumper(\%cat_items));

    __DATA__
    ...xml...

    PS - 你所拥有的不是有效的 HTML。
  • TABLE 元素不能直接放在 TR 元素内。缺少 TD 元素。
  • TR 元素不能为空。它必须至少有一个 TH 或 TD 元素。
  • 关于带有条件的 Perl XPath 语句 - 这可能吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9070243/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com