【问题标题】:Doctype sniffing with CSS3, and specifically with Mojo::DOM使用 CSS3 进行 Doctype 嗅探,特别是使用 Mojo::DOM
【发布时间】:2015-12-05 00:50:36
【问题描述】:

我可以使用Mojo::DOM 及其CSS3 选择器来确定HTML 文档的DOCTYPE 吗?与我的另一个问题有关,How should I process HTML META tags with Mojo::UserAgent? 我想在哪里设置文档的字符集,我需要知道要查看什么,doctype sniffing 似乎是这样做的方法。当文档设置覆盖服务器设置(或非设置)时,HTML 和 HTML 5 对 HTML 中的字符集具有不同的元标记。

我完成任务没有问题,因为我可以获取原始响应并使用正则表达式来查看 DOCTYPE。 Since the browser DOMs seem to be able to get the DOCTYPE,我被我应该能够得到它的想法所感染。但是,由于缺乏示例,我认为没有人会按照我认为我应该做的方式去做。

我尝试了很多愚蠢的方法,但我的 CSS 功夫很弱:

use v5.20;

use feature qw(signatures);
no warnings qw(experimental::signatures);

use Mojo::DOM;

my $html = do { local $/; <DATA> };

my $dom = Mojo::DOM->new( $html );

say "<title> is => ", $dom->find( 'head title' )->map( 'text' )->each;

say "Doctype with find is => ", $dom->find( '!doctype' )->map( 'text' )->each;

say "Doctype with nodes is => ", $dom->[0];

__DATA__

<!DOCTYPE html>
<head>
<title>This is a title</title>
</head>
<body>
<h1>Level 1</h1>
</body>
</html>

当我转储 $dom 对象时,我在树中看到 DOCTYPE:

$VAR1 = bless( do{\(my $o = bless( {
                      'tree' => [
                                  'root',
                                  [
                                    'text',
                                    '',
                                    ${$VAR1}->{'tree'}
                                  ],
                                  [
                                    'doctype',
                                    ' html',
                                    ${$VAR1}->{'tree'}
                                  ],

现在我该怎么做?

【问题讨论】:

  • 似乎没有内置的方法可以做到这一点,因为文档类型存储在树的顶层。我能想到的最好的办法是:my %ugly_tree = @{ $dom-&gt;root-&gt;tree }; my ($doctype) = $ugly_tree{doctype}; 但这可能很脆弱。
  • doctype只是另一个节点,您可以使用child_nodes等方法找到它们。

标签: html perl css mojolicious mojo-dom


【解决方案1】:

确定 HTML5 文档的编码非常complex。恐怕Mojo::DOM 只是一个片段解析器,因此我们决定编码嗅探算法的完整实现将超出范围。谢天谢地,大多数网络都是 UTF-8 编码的,我想这就是为什么这个问题不经常出现的原因。

【讨论】:

  • 我的问题要简单一些:我只想确定他们所说的字符集是什么,即使它是错误的。有一个特定的错误配置的 Web 服务器引发了这个问题。 :)
【解决方案2】:

我仍然认为有希望找到更好的方法来做到这一点,但也许我对Mojo::UserAgent 承担了太多责任。我可以建立一个事务并将finish 事件添加到响应中。在那种情况下,我使用正则表达式嗅探内容并添加带有 doc 类型的 X- 标头。我可能可以通过其他方式传递信息,但这不是重点(尽管仍在接受建议!)

use v5.14;

use Mojo::UserAgent;

@ARGV = qw(http://blogs.perl.org);

my $ua = Mojo::UserAgent->new;

my $tx = $ua->build_tx( GET => $ARGV[0] );
$tx->res->on( finish => sub {
    my $res = shift;
    my( $doctype ) = $res->body =~ m/\A \s* (<!DOCTYPE.*?>)/isx;
    if( $doctype ) {
        say "Found doctype => $doctype";
        $res->headers->header( 'X-doctype', $doctype );
        }
    });
$tx = $ua->start($tx);

say "-----Headers-----";
say $tx->res->headers->to_string =~ s/\R+/\n/rg;

这是输出:

Found doctype => <!DOCTYPE html>
-----Headers-----
Connection: Keep-Alive
Server: Apache/2.2.12 (Ubuntu)
Content-Type: text/html
Content-Length: 20624
Accept-Ranges: bytes
X-doctype: <!DOCTYPE html>
Last-Modified: Wed, 16 Sep 2015 13:08:26 GMT
ETag: "26d42e8-5090-51fdcfe768680"
Date: Wed, 16 Sep 2015 13:40:02 GMT
Keep-Alive: timeout=15, max=100
Vary: Accept-Encoding

现在我必须考虑各种事情来解析 DOCTYPE 值并根据这些决定如何处理内容。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-30
    • 1970-01-01
    • 1970-01-01
    • 2012-10-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-07-22
    相关资源
    最近更新 更多