基于Mojo与Mechanize的Perl高效爬虫实现

Perl 虽然不像 Python 那样是当今爬虫领域的绝对主流,但它凭借其独特的优势,在特定场景下与爬虫结合能碰撞出非常惊艳的火花,尤其是在文本处理、快速原型、系统集成和遗留系统维护方面。

以下是一个利用Perl特性实现的爬虫示例,融合了正则表达式威力、Mojo现代工具链、Mechanize自动化和管道处理等特色功能:

perl 复制代码
#!/usr/bin/env perl
use strict;
use warnings;
use Mojo::UserAgent;
use Mojo::DOM;
use WWW::Mechanize;
use Text::Table;  # 生成表格输出
use File::Slurp;  # 简洁文件操作
​
# 特色1: Mojo异步并发爬取
sub mojo_concurrent_crawl {
    my $ua = Mojo::UserAgent->new(max_redirects => 3);
    $ua->transactor->name('Mozilla/5.0 (Windows NT 10.0; rv:91.0) Gecko/20100101 Firefox/91.0');
    
    # 创建异步采集队列
    my @urls = (
        'https://news.ycombinator.com',
        'https://www.perl.org',
        'https://github.com/topics/perl'
    );
    
    # 特色2: 使用->ioloop实现并发控制
    my $delay = Mojo::Promise->new;
    my $count = 0;
    
    for my $url (@urls) {
        my $promise = $ua->get_p($url)->then(sub {
            my ($tx) = @_;
            
            # 特色3: Mojo::DOM的CSS选择器
            my $dom = $tx->result->dom;
            print "★ 来自 " . $tx->req->url->host . " 的标题:\n";
            
            # 特色4: Perl特有的map链式处理
            my @titles = $dom->find('h1, h2, h3')->map('text')->grep(qr/perl/i)->uniq->each;
            print "  $_\n" for @titles;
            
            # 特色5: 强大的正则表达式提取
            $dom->find('a')->each(sub {
                my ($e) = @_;
                if ($e->attr('href') =~ m{
                    .(pdf|ppt|docx?)   # 捕获文档类型
                    (?:?.*)?$          # 忽略查询参数
                }six) {
                    print "  发现文档: " . $e->attr('href') . "\n";
                }
            });
        })->catch(sub {
            my $err = shift;
            warn "🚨 $url 请求失败: $err";
        });
        
        $delay = $delay->then($promise);
        last if ++$count >= 5;  # 限制并发数
    }
    
    $delay->wait;
}
​
# 特色6: Mechanize表单交互式爬取
sub mech_form_crawler {
    my $mech = WWW::Mechanize->new(autosave => 1);
    $mech->agent_alias('Windows Chrome');
    
    $mech->get('https://example.com/login');
    
    # 特色7: 智能表单填写
    $mech->submit_form(
        form_number => 1,
        fields      => {
            username => 'perl_bot',
            password => 'camel_123'
        },
    );
    
    # 特色8: 链接过滤采集
    my @links = $mech->find_all_links(url_regex => qr/archive/);
    for my $link (@links) {
        next unless $link->url =~ m{/202[34]/};  # 正则过滤
        
        $mech->get($link->url);
        my $content = $mech->content;
        
        # 特色9: 多行正则提取
        if ($content =~ m{
            <div\s+class="article">   # 开始标记
            (.*?)                      # 惰性匹配内容
            </div>                     # 结束标记
        }xms) {
            my $article = $1;
            
            # 特色10: 就地内容清洗
            $article =~ s/<script.*?</script>//gs;  # 删除脚本
            $article =~ s/<[^>]+>//g;                # 移除所有标签
            $article =~ s/\s{2,}/ /g;                # 压缩空白
            
            # 保存处理结果
            write_file("data/".time().".txt", {binmode => ':utf8'}, $article);
        }
    }
}
​
# 特色11: 管道式数据处理
sub pipeline_processing {
    open my $pipe, '|-', 'grep "Perl" | sort | uniq -c | head -n 20' or die $!;
    
    my @sites = qw(
        https://www.reddit.com/r/perl
        https://stackoverflow.com/questions/tagged/perl
    );
    
    my $ua = Mojo::UserAgent->new;
    foreach my $url (@sites) {
        my $tx = $ua->get($url);
        my $text = $tx->result->text;
        
        # 特色12: 一行式正则提取
        my @matches = $text =~ /(\b\w*perl\w*\b)/gi;
        
        print $pipe "$_\n" for @matches;
    }
    close $pipe;
}
​
# 执行示例
mojo_concurrent_crawl();

Perl爬虫特色解析:

1、正则表达式核武器

ruby 复制代码
$article =~ s/<script.*?</script>//gs;  # 精准清除脚本标签
$link->url =~ m{/202[34]/}              # 路径智能过滤

2、Mojo现代工具链

perl 复制代码
$ua->get_p($url)->then(sub {...})  # Promise异步处理
$dom->find('h1')->map('text')->grep(qr/perl/i) # 链式选择器

3、Mechanize自动化

ini 复制代码
$mech->submit_form(              # 自动表单提交
  fields => {username => 'bot'} 
);

4、UNIX管道集成

perl 复制代码
open my $pipe, '|-', 'grep "Perl" | sort | uniq -c'; # 直接调用系统管道

5、命令行魔法: 单行抓取示例:

arduino 复制代码
perl -MLWP::Simple -e 'getprint "https://example.com"' | perl -nE '/<title>(.*?)</ && say $1'

6、智能内容提取

ini 复制代码
# 多行跨行匹配
$content =~ m{<div class="article">(.*?)</div>}xms;

7、防御式编程

bash 复制代码
$ua->max_redirects(3);  # 防重定向陷阱
$mech->autosave(1);     # 自动保存会话

典型应用场景:

  • 数据挖掘:用正则快速清洗非结构化数据
  • 自动化测试:Mechanize模拟用户工作流
  • 内容聚合:Mojo并发采集多源数据
  • 遗留系统:集成Shell脚本和Perl模块
  • 日志分析:管道处理实时数据流

Perl爬虫在文本处理密集型任务中表现尤为出色,其正则表达式引擎处理复杂文本模式的速度比通用语言快3-5倍,特别适合处理老旧网站的非标准HTML。通过组合CPAN模块(如Mojo的异步能力+Mechanize的浏览器模拟),可构建出既高效又灵活的采集方案。

虽说 Python 现在是爬虫领域的"当红炸子鸡",但 Perl 远未过时。它在处理复杂文本、快速开发小型到中型爬虫、深度系统集成以及应对非标准解析挑战方面,依然能迸发出独特而惊艳的火花。尤其是在文本处理的核心能力上,Perl 仍然是顶尖高手。如果大家已经熟悉 Perl,或者面临的任务高度依赖文本解析和灵活性,Perl 绝对是一个值得考虑甚至能带来惊喜的选择。对于追求极致文本处理速度和灵活性的开发者,Perl 爬虫依然是一把锋利无比的"手术刀"。

相关推荐
就是帅我不改3 小时前
深度模拟用户行为:用Playwright爬取B站弹幕与评论数据
爬虫·数据挖掘
Damon小智3 小时前
基于华为开发者空间的Open WebUI数据分析与可视化实战
华为·ai·数据挖掘·数据分析
华科云商xiao徐6 小时前
PowerShell部署Windows爬虫自动化方案
爬虫·数据挖掘·数据可视化
华科云商xiao徐6 小时前
Nim开发高性能低成本爬虫的完整教程
大数据·爬虫·数据挖掘
菜鸟冲锋号8 小时前
数据建设之明细层指标和汇总层指标结合方式
大数据·机器学习·数据挖掘
青云交8 小时前
Java 大视界 -- Java 大数据在智能医疗电子病历数据分析与临床决策支持中的应用(382)
java·大数据·数据分析·flink·电子病历·智能医疗·临床决策
派可数据BI可视化19 小时前
CIO如何规划企业BI分析指标体系 —— 从经营出发到绩效管理
数据仓库·信息可视化·数据挖掘·数据分析·商业智能bi
没有梦想的咸鱼185-1037-166319 小时前
Python科研数据可视化技术
python·机器学习·信息可视化·数据分析
SelectDB20 小时前
森马服饰从 Elasticsearch 到阿里云 SelectDB 的架构演进之路
大数据·数据库·数据分析