html - Perl 网络抓取工具,从脚本标签内的文本中检索数据

标签 html perl web-scraping web-crawler

到目前为止,我使用 perl 从使用 HTML::TreeBuilder 的网页获取数据。当数据包含在 metadiv 标签中时,这是可以的;但现在我偶然发现了一个我不知道如何爬行的新结构,尽管它看起来很微不足道。

<html lang="en">
    <body>
        <script type="text/javascript">
            panel.web.bootstrapData = {
                "data": {
                    "units": "kW",
                    "horsePower": 100.00
                }
            };
        </script>
    </body>
</html>

该示例显示了我从网络上获取的内容的相关部分。我想获取 unitshorsePower 的值。

到目前为止我使用的代码片段:

use strict;
use LWP::UserAgent;
use HTTP::Request::Common;
use HTML::TreeBuilder;

[...]

$reply = $ua->get($url, @ns_headers);

# printing the reply would get us the first code snippet.
print $reply->content;

unless ($reply->is_success) {
    [...]
}

my $tree = HTML::TreeBuilder->new_from_content($reply->content);
my @unit_array = $tree -> look_down(_tag=>'meta','itemprop'=>'unit');
my $unit = $unit_array[0]->attr('content');

[...]

有谁知道如何获取相关数据以及我是否应该为此使用 HTML::TreeBuilder 以外的东西?我通过stackoverflow和网络搜索都没有发现任何类似的案例。

最佳答案

你基本上是在正确的道路上。但是HTML::TreeBuilder对 JavaScript 一无所知。

方法:

  • 找到<script>节点
  • 从这些节点中提取 JSON 内容
    • 注意:这对于给定的示例来说很容易,但对于更复杂的 <script> 则需要更多的技巧。内容
    • 越狱 \;在正则表达式中并不是真正需要的,但是没有它 SO 语法高亮器会变得困惑
  • 使用JSON将字符串解码为 Perl 数据结构
  • 在脚本中访问这些数据结构

第一个没有错误检查的粗略解决方案。我在代码中留下了一些调试行,注释掉了,以便您可以跟踪每个步骤在做什么:

#!/usr/bin/perl
use strict;
use warnings;

use Data::Dumper;
use HTML::TreeBuilder;
use JSON;

my $decoder = new JSON;

my $tree       = HTML::TreeBuilder->new_from_file(\*DATA);
#$tree->dump;
my @scripts    = $tree->look_down(_tag => 'script');
#$scripts[0]->dump;
# NOTE 1: ->as_text() *DOES NOT* return <script> content!
# NOTE 2: ->as_HTML() probably doesn't work for all cases, i.e. escaping
my $javascript = ($scripts[0]->content_list())[0];
#print "${javascript}\n";
my($json)      = $javascript =~ /(\{.+\})\;/s;
#print "${json}\n";
my $object     = $decoder->decode($json);

print Dumper($object);
print "FOUND: units: ", $object->{data}->{units},
      " horsepower: ",  $object->{data}->{horsePower}, "\n";

# IMPORTANT: $tree needs to be destroyed by hand when you're done with it!
$tree->delete;

exit 0;

__DATA__
<html lang="en">
    <body>
        <script type="text/javascript">
            panel.web.bootstrapData = {
                "data": {
                    "units": "kW",
                    "horsePower": 100.00
                }
            };
        </script>
    </body>
</html>

测试运行:

$ perl dummy.pl
$VAR1 = {
          'data' => {
                      'horsePower' => '100',
                      'units' => 'kW'
                    }
        };
FOUND: units: kW horsepower: 100

关于html - Perl 网络抓取工具,从脚本标签内的文本中检索数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54840931/

相关文章:

perl - 我如何将 Perl 的 'prove' 与其他语言的 TAP 生产者一起使用?

java - 如何抓取 HTTPS javascript 网页

html - 了解 CSS 选择器优先级/特异性

perl - 使用 bash/tail/perl/alias 轻松突出显示不同的字符串

javascript - offsetParent.scrollTop 在大多数浏览器中不起作用

regex - 如何修复 Perl Getopt::Long 事件未找到错误?

java - 从重复的层次结构中删除 Selen

python - 即使使用正确的 xpath,Scraper 也会抛出错误

javascript - 看不到进度条标签

html - 如何使一个元素低于另一个 float 元素