【问题标题】:Creating multiple files for each tld and sorting each file为每个 tld 创建多个文件并对每个文件进行排序
【发布时间】:2011-12-23 23:18:05
【问题描述】:

我有一百万个网址的列表。我必须为每个 url 提取 TLD 并为每个 TLD 制作多个文件。例如收集所有带有 .com 的网址作为 tld 并将其转储到 1 个文件中,另一个申请 .edu tld 等等。在每个文件中,我必须按域名的字母顺序对其进行排序,然后按子域等进行排序。 ct 任何人都可以在 perl 中应用它吗?

我已使用 URI 模块来提取每个网址的 tld 以及域名和主机名。 如何使用 com tld 收集所有网址并将它们转储到 1 个文件中? 以及如何按 tld 对每个文件进行排序,然后按域然后按子域等? 有什么指点吗?

while(my $line = <$fh1>){   

my $url = $line;

 my @components =  split(/\./, $url);
 my $n_comp = ($components[-1] =~ /^edu|com|net|org|gov$/) ? 2 : 3;
 my $domain = lc(join '.', @components[-$n_comp .. -1]);
 $domain =~ s/^\.//;  # Remove leading . if there is one.
 print $fh3 $domain;
        print $fh3 "\n";


  my $host = URI->new($url)->host();

 # Treat relative URLs as absolute URLs with missing http://.
 $url = "http://$url" if $url !~ /^\w+:/;



 $host =~ s/\.\z//;  # D::PS doesn't handle "domain.com.".
 print $fh2 $host;
 print $fh2 "\n";
 $dps->get_root_domain($host)
 or die $dps->error();
 print $fh4 $dps->tld();
 print $fh4 "\n";


 }

【问题讨论】:

  • 输出是否必须具有特定格式?它必须易于人类/计算机阅读吗?
  • 在其组件中拆分域是正确的开始。现在您必须编写一个比较函数来比较从 TLD 开始到子域的两个组件数组。最大的障碍是处理不同长度的组件数组。
  • @BradGilbert 是的,它必须是人类可读的格式......问题是一个域可以有多个 Ip,而 eaxh 域可以有多个名称服务器,每个名称服务器有多个 IP,我该如何输出这个perl 中的文件?

标签: perl tld


【解决方案1】:

这应该适合你。

use strict;
use warnings;
use autodie;

open my $input, '<', shift @ARGV;
my %domain;
while( <$input> ){
  chomp;
  #                                   (  protocol   ) (  domain ) (rest)
  my ($protocol,$domain,$remain) = /^ (?:(\w+):\/\/)? ([^\\\/#]+) ( .* ) /x;

  my ($tld,@domain) = reverse split /[.]/, $domain;

  my $cmp = join '.', @domain;
  push @{ $domain{$tld} }, [ $cmp, $remain, $_ ];
}
close $input;

while( my($tld,$list) = each %domain ){
  open my $out, '>', $tld;
  print {$out} "$_\n" for map{
    $_->[-1]
  }sort{
    $a->[0] cmp $b->[0] ||
    $a->[1] cmp $b->[1] ||
    $a->[2] cmp $b->[2]
  } @$list;
  close $out;
}

  1. 首先我们将输入分解成我们需要的部分。

    /^ (?:(\w+):\/\/)? ([^\\\/#]+) ( .* ) /x;
    
    • 这将匹配可选的http:// 或类似的。

      (?:(\w+):\/\/)?
    • 这匹配除\/# 之外的任何内容,因为这些字符通常出现在域之后。

      ([^\\\/#]+)
    • 这当然匹配剩下的任何东西。

      ( . )
  2. 我们希望从顶级域到最低级域对 URL 进行排序。所以我们split 域,然后reverse 它。

    my ($tld,@domain) = reverse split /[.]/, $domain;
    
  3. 要比较两个 URL,我们需要一个易于比较的字符串。

    my $cmp = join '.', @domain;
    
  4. 存储信息以备后用。

    push @{ $domain{$tld} }, [ $cmp, $remain, $_ ];
    
  5. Open我们要打印到的文件。

    while( my($tld,$list) = each %domain ){
      open my $out, '>', $tld;
    
  6. Sort 进入当前文件的 URL 列表。

    ...
    sort{
      $a->[0] cmp $b->[0] ||
      $a->[1] cmp $b->[1] ||
      $a->[2] cmp $b->[2]
    } @$list;
    
  7. Map 列表指向实际的 URL。

    ...
    map{
      $_->[-1]
    }
    ...
    
  8. Print 到文件列表中的每个 URL。

    print {$out} "$_\n" for ...
    

【讨论】:

  • 非常感谢@BradGilbert 的全面解释!你能告诉我这里到底发生了什么吗:push @{ $domain{$tld} }, [ $cmp, $remain, $_ ];
猜你喜欢
  • 2021-05-21
  • 1970-01-01
  • 2021-03-26
  • 1970-01-01
  • 2020-03-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-15
相关资源
最近更新 更多