【问题标题】:Regex get column information based on other column正则表达式根据其他列获取列信息
【发布时间】:2019-06-20 05:33:18
【问题描述】:

我有这个:

<table border="1" cellspacing="1" cellpadding="0">

<tbody>

<tr><th class="align-left" style="text-align: left;">Name</th><th>Type</th><th>Size</th><th>Values</th><th>Description</th><th>Attributes</th><th>Default</th></tr>

<tr>

<td>E-mail</td>

<td>text</td>

<td>60</td>

<td>test@test.com</td>

<td>&#160;</td>

<td>M</td>

<td>test@test.com</td>

</tr>

<tr>

<td>Phone</td>

<td>text</td>

<td>20</td>

<td>01-250 481 00</td>

<td>&#160;</td>

<td>&#160;</td>

<td>&#160;</td>

</tr>

</tbody>

</table>

代码如下所示:

我想使用正则表达式/正则表达式从(名称)的左侧提取(值)中的信息,但我不知道这是否可能......

比如我想搜索“电话”,得到“01-250 481 00”

你怎么看?

【问题讨论】:

标签: html regex perl


【解决方案1】:

不要使用正则表达式来解析 HTML。使用 HTML 解析器将 HTML 转换为 DOM 树。然后在 DOM 域中执行您的操作。例如

use HTML::TreeParser;

my $parser = HTML::TreeParser->new;
my $root   = $parser->parse_content($html_string);

my $table = $root->look_down(_tag => 'table');
my @rows  = $table->look_down(_tag => 'tr');
for my $row (@rows) {
    # perform your row operation here using HTML::Element methods
    # search, replace, insert, modify content...

    my @columns = $row->look_down(_tag => 'tr');

    # we need 1st (Name) and 4th (Values) column
    if (@columns >= 4) {
        if ($column[0]->as_trimmed_text() eq "Phone") {
            my $number = $column[3]->as_trimmed_text();
            ...
        }
    }
}

# if you need to dump the modified tree again...
print $root->as_HTML();

# IMPORTANT: must be done after done with DOM tree!
$root->delete();

【讨论】:

    【解决方案2】:

    Mojo::DOM 选项:

    use strict;
    use warnings;
    use Mojo::DOM;
    use List::Util 'first';
    
    my $dom = Mojo::DOM->new($html);
    my $query = 'phone';
    
    my @cols = $dom->at('tr')->find('th')->map('text')->each;
    my $name_col = 1 + first { $cols[$_] eq 'Name' } 0..$#cols;
    my $values_col = 1 + first { $cols[$_] eq 'Values' } 0..$#cols;
    
    my $row = $dom->find('tr')->first(sub {
      my $name = $_->at("td:nth-of-type($name_col)");
      defined $name and $name->text =~ m/\Q$query\E/i;
    });
    
    if (defined $row) {
      my $values = $row->at("td:nth-of-type($values_col)")->text;
      print "Values: $values\n";
    } else {
      print "Not found\n";
    }
    

    【讨论】:

      【解决方案3】:

      用正则表达式解析 HTML 是个糟糕的主意。我目前解析 HTML 时选择的武器是Web::Query

      我的方法是将表格解析为合适的数据结构,然后您可以提取所需的数据。

      可能是这样的……

      #!/usr/bin/perl
      
      use strict;
      use warnings;
      use feature 'say';
      
      use Data::Dumper;
      use Path::Tiny;
      use Web::Query;
      
      # Get the HTML. I'm reading it from a file, you might
      # need to make an HTTP request.
      my $html = path('table.html')->slurp;
      
      # Parse the HTML.
      my $wq = wq($html);
      
      # Extract the text from all of the <th> elements.
      # These will be the keys of our hash.
      my @cols;
      $wq->find('th')->each(sub { push @cols, $_->text });
      
      # A hash to store our data
      my %data;
      
      # Find all of the <tr> elements in the HTML
      $wq->find('tr')->each(sub {
        # Each table row will be a sub-hash in our hash
        my %rec;
        # Find each <td> element in the row.
        # For each element, get the text and match it with the column header.
        # Store the key/value pair in a hash.
        $_->find('td')->each(sub {
          my ($i, $elem) = @_;
          my $key = $cols[$i];
          $rec{$key} = $elem->text;
        });
        # If we have data, then store it in the main hash.
        $data{$rec{Name}} = \%rec if $rec{Name};
      });
      
      # Show what we've made.
      say Dumper \%data;
      
      # A sample query which extracts all of the values
      # from the data structure.
      for (keys %data) {
        say "$_ is $data{$_}{Values}";
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-11-19
        • 1970-01-01
        • 2016-09-08
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多