【问题标题】:Is there any way to fetch web pages in pure perl?有没有办法在纯 perl 中获取网页?
【发布时间】:2016-02-25 03:15:14
【问题描述】:

我正在一台旧的、过时的嵌入式 ARM 计算机上进行开发,并且没有可用于 HTTP 客户端支持的模块。没有 LWP,没有 HTTP::Tiny 等。

我无法为这个平台编译任何东西。原来的开发者早已离开公司,这个项目目前处于维护模式。

有什么方法可以让我使用纯 perl 获取 HTTP 页面,最好是 HTTPS 页面?我可以将任何模块复制到库树中(不支持 CPAN...)?

谢谢。

编辑:perl 解决方案失败我想我可以退回到从 perl 脚本运行 wget 或 curl ——但是内存非常有限,所以我想尽可能避免这种情况。

【问题讨论】:

  • 我相信HTTP::Tiny 是纯粹的 Perl。您甚至可能已经拥有它;自 Perl 5.14 以来,它一直是核心模块(尽管它需要 SSL 的非核心模块)。
  • 你有什么版本?你有哪些核心模块?
  • “只是复制”是什么意思?没有C,好的……还有什么可以吗?
  • 我的意思是将 .pm 文件从模块分发中复制到我的库树中。
  • LWP 也是纯 Perl,但 LWP::Protocol::https 具有 C 依赖项。 HTTPS 支持总是需要 C 依赖。

标签: perl arm embedded


【解决方案1】:

您可以在没有库的情况下进行普通的套接字编程。 Perl 支持大多数 POSIX/c 库来做到这一点。根据您有多少可用的标准库,您的解决方案会有所不同。如果你有像 IO::Socket::INET 这样的普通套接字,我会推荐 HTTP::Tiny,比如 @ThisSuitIsBlackNot。

这是一个仅使用 Socket 的程序,如果您需要实现自己的 HTTP 客户端,它应该可以帮助您入门。

use strict;
use warnings;
use Socket qw(PF_INET SOCK_STREAM pack_sockaddr_in inet_aton);

socket(my $socket, PF_INET, SOCK_STREAM, 0) or die "socket: $!";
my $port = getservbyname "http", "tcp";
connect($socket, pack_sockaddr_in($port, inet_aton("www.google.com"))) or die "connect: $!";

send($socket, "GET / HTTP/1.0\r\n", 0);
send($socket, "Host: www.google.com\r\n", 0);
send($socket, "User-Agent: pureperl\r\n\r\n", 0);

while (my $line = <$socket>)
{
    print $line;
}

如果您也没有 Socket,则需要手动获取 PF_INET、SOCK_STREAM 和这两个函数的值。

如果你有 IO::Socket 最好使用它:

use strict;
use warnings;    
use IO::Socket;
$sock = IO::Socket::INET->new(PeerAddr => 'www.google.com',
                              PeerPort => 'http(80)',
                              Proto    => 'tcp');
$sock->send("GET / HTTP/1.0\r\n");
$sock->send("Host: www.google.com\r\n");
$sock->send("User-Agent: pureperl\r\n");
$sock->send("\r\n");

while (my $line = <$sock>)
{
    print $line;
}

但是如果你有 IO::Socket,那么如果你只是复制它,那么 HTTP::Tiny 中的 Tiny.pm 应该会加载。

我不建议尝试在纯 perl 中解决 HTTPS,或者从您自己的实现开始。

【讨论】:

  • https 手卷太可怕了。生命对于那种痛苦来说太短暂了。
  • 我尝试安装 HTTP::Tiny,但是 make 脚本在找不到 CORE/config.h 时被拒绝,所以我认为它需要在 C 中编译一些东西。我应该更接近查看分布以确认。
  • 非常感谢您发布 Socket 示例,我确实有 Socket 和 IO::Socket 可用,所以现在就可以了(HTTPS 可以稍后出现)。
  • @NXT:您应该检查您是否有可用的 IO::Socket 以节省您的一些心痛。 HTTP::Tiny 也不需要 C 编译器,但它的某些要求可能确实如此。如果你有 IO::Socket 你应该能够编辑模块来工作。
  • @bolav:只需将 .pm 文件复制到我的库目录中,我就能让 HTTP::Tiny 正常工作。感谢您的建议。
【解决方案2】:

perl 解决方案失败我想我可以退回到从 perl 脚本运行 wget 或 curl ——但内存非常有限,所以我想尽可能避免这种情况。

这毫无意义,curl 使用的内存比 LWP 少。

加载 LWP 在我的机器上使用了将近 3,000 KiB。 curl 的图片大小只有 125 KiB。

使用curl

【讨论】:

  • 我承认我的部分反对意见是为此运行另一个进程是丑陋的,而且我的直觉是减少进程启动开销。但我不知道差异如此明显。
  • 这些是粗略的测量。我实际上并没有测量curl 内存占用量,但规模的差异不言而喻。 // 至于启动开销,curl 更高的速度应该很容易弥补。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-07-09
  • 1970-01-01
  • 1970-01-01
  • 2017-12-29
  • 2011-02-05
  • 1970-01-01
  • 2015-10-05
相关资源
最近更新 更多