【问题标题】:Generate the output on a particular cell ID in CSV在 CSV 中生成特定单元 ID 的输出
【发布时间】:2015-10-13 07:34:08
【问题描述】:

我在这里想要实现的是将 标签 HTML 中的 values 提取到我成功的 CSV 文件中。我想要的是对正在生成的输出进行一些控制

HTML 值是:

<input type=hidden id=batterystatus value="Charging" >
<input type=hidden id=batterylevel value="80&nbsp;%" >
<input type=hidden id=signalStrength value="4" >
<input type=hidden id=ulCurrentDataRate value="5 Kbps" >
<input type=hidden id=dlCurrentDataRate value="136 Kbps" >
<input type=hidden id=ConnectionTime value="00:15:33:10" >
<input type=hidden id=noOfClient value="2" >  

现在,我使用 perl 编写脚本。

#!usr/bin/perl

use strict;
use warnings;
use HTML::TokeParser::Simple;

my $url = 'http://192.168.225.1';
my $parser = HTML::TokeParser::Simple->new(url => $url);
my %tags;
while (my $tag = $parser->get_tag('input')) {
           my $id=$tag->get_attr('id'); # get id attribute value    
           my $value = $tag->get_attr('value'); # get value attribute value
           $tags{$id}=$value;
 }
my @tags;
my @values;
for (keys %tags){
   push (@tags, $_);
   push (@values, $tags{$_});
}

open(my $OUTFILE, ">", "test.csv")
    or die "Unable to open testfile for writing : $!";
print $OUTFILE join(",",@tags)."\r\n";
print $OUTFILE join(",",@values)."\r\n";

CSV文件中生成的数据是:

然后当我重新运行这段代码时,我发现了这样的东西:

问题:

  1. 如何修复单元格 ID,这样我总是在 Cell A1 中得到 IMSI 以及特定单元格中的其他输出?
  2. 如何重命名每个单元格标题?例如batterylevel 重命名为Battery LevelconnectedStatus 重命名为Connected Status

【问题讨论】:

  • Sidenode:你知道&lt;input&gt;id 不是表单使用的标识符吗?那些使用name。只是说。 :)
  • @simbabque - 问题已被编辑。添加了示例 HTML 代码
  • 我想知道如果输入中没有名称,这是一个什么样的页面。可能是 Kies Air 状态页面或类似的移动设备具有网络服务器并且您可以从网络访问它的地方?关键是,这些列没有排序,但它们都存在。
  • @simbabque - 我没有复制整个 html 页面,因为我更关心从那里挑选出值。如果你想看看,请告诉我,我也会分享。

标签: perl csv automation


【解决方案1】:

您正在使用哈希来存储数据,并且在访问值时没有对其进行排序。 Perl 中的哈希未排序。键的顺序是随机的,(at least in recent Perls) 你不能依赖这个顺序。您需要自己对键进行排序。 这是一项功能

最简单的方法是对订单进行硬编码,因为看起来您总是期待相同的输入。要重命名列,只需使用哈希作为查找表。

我使用了Text::CSV,因为它经过了很好的测试,甚至可以很好地处理神秘的边界情况。

use strict;
use warnings;
use HTML::TokeParser::Simple;
use Text::CSV;

my $html = <<HTML;
<input type=hidden id=imsi value="406E+14" >
<input type=hidden id=batterystatus value="Charging" >
<input type=hidden id=batterylevel value="80&nbsp;%" >
HTML

my $parser = HTML::TokeParser::Simple->new( string => $html );

# mapping for the column headers
my %names = (
    imsi          => 'IMSI',
    batterylevel  => 'Battery Level',
    batterystatus => 'Battery Status',
);

my %tags;
while ( my $tag = $parser->get_tag('input') ) {
    my $id    = $tag->get_attr('id');       # get id attribute value
    my $value = $tag->get_attr('value');    # get value attribute value
    $tags{$id} = $value;
}

# use meaningfull names and sort in the loop
my @headers;
my @values;
foreach my $tag (qw(imsi batterylevel batterystatus)) {
    push @headers, $names{$tag};
    push @values,  $tags{$tag};
}

# create a T::CSV handle with Win line endings
my $csv = Text::CSV->new({
  sep_char => ',',
  eol => "\r\n",
  quote_char => q{},
});

# write out headers and values
$csv->print(\*STDOUT, \@headers);
$csv->print(\*STDOUT, \@values);

【讨论】:

  • 我收到一个错误Global symbol "@tags" requires explicit package name at htmlparse_test.pl line &lt;some line number&gt;. Execution of htmlparse_test.pl aborted due to compilation errors.
  • 但我正在使用它,因为我需要将数据写入 csv 文件。你能看看那个 pastebin 代码吗?
  • 对您的 pastebin 链接的反馈:将 open 移动到 Text::CSV-&gt;new 上方,将 \*STDOUT 替换为 $OUTFILE(最好命名为 $fh,全大写名称建议全局变量,它是一个句柄而不是文件)并摆脱 print join 行。
  • 在我的回答中,Text::CSV 正在为您处理 CSV 文件。它已经做了你想要的。当然,您仍然可以自己做print。我所做的只是将变量重命名为更有意义的名称。 :)
猜你喜欢
  • 1970-01-01
  • 2017-04-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多