用Perl中的HTML对应项替换特定的内联CSS

用Perl中的HTML对应项替换特定的内联CSS,perl,Perl,这是我第一次使用堆栈溢出,所以如果我做错了什么,请告诉我 由于缺少更好的术语,我目前正在尝试编写一个“scraper”,它将提取html并用html对应项替换某些内联CSS样式。例如,我有以下HTML: <p style="text-align:center"><span style="font-weight:bold;font-style:italic;">Some random text here. What's here doesn't matter so much

这是我第一次使用堆栈溢出,所以如果我做错了什么,请告诉我

由于缺少更好的术语,我目前正在尝试编写一个“scraper”,它将提取html并用html对应项替换某些内联CSS样式。例如,我有以下HTML:

<p style="text-align:center"><span style="font-weight:bold;font-style:italic;">Some random text here. What's here doesn't matter so much as what needs to happen around it.</span></p>
希望有人能帮助我,让我看看我做错了什么,等等。我真的很好奇还有什么其他可能的方法可以做到这一点。或者如果以前做过的话


另外,如果有人能帮忙建议我应该使用哪些标签,那就太好了。我知道唯一可以肯定使用的是perl。

从HTML::Element文档中,似乎look_down()返回了HTML::Element对象的列表。perl对象通常是对哈希的引用(尽管它们不需要)——这就是为什么打印
$span
时会得到哈希

无论如何,在for循环中,您应该能够调用

 $span->method()
其中method是HTML::Element的任何方法。出于您的目的,方法
all_attr()
as_text()
,以及
replace_with()
看起来很有希望

我尝试链接到每个方法,但不喜欢粗糙的CPAN锚定链接,因此为了方便起见,这里有一个指向主文档页面的快速链接:

迈克,
问题是,在Perl中,您很遗憾无法在调试器中看到元素的类型,因为对象系统只是标准类型的包装器。因此,在查看文档和/或代码时,不可能找到相关属性/方法。为您提供有关此的更多详细信息。
每$span将是一个HTML::Element对象——Ben的回答涵盖了这一部分。我猜您只需更改树中的一些属性,并将树保存到一个新文件。

通过使用,您肯定走上了正确的道路;对于分析CSS,我刚刚发现。这是一个非常有趣的模块,它允许您轻松访问属性

#!/usr/bin/perl
use warnings;
use strict;

use HTML::TreeBuilder;
use CSS::DOM::Style;

my $html = <<HTML;
<p style="text-align:center"><span style="font-weight:bold;font-style:italic;">Some random text here. What's here doesn't matter so much as what needs to ha>
HTML

my $tb = HTML::TreeBuilder->new_from_content($html);


my @replacements = (
    { property => 'font-style', value => 'italic', replacement => 'em' },
    { property => 'font-weight', value => 'bold', replacement => 'strong' },
    { property => 'text-align', value => 'center', replacement => 'center' },
);

# build a sensible list of tag names (or just use sub { 1 })
my @nodes = $tb->look_down(sub { $_[0]->tag =~ /^(p|span)$/ });

for my $el (@nodes) {
    if ($el->attr('style')) {
        my $st = CSS::DOM::Style::parse($el->attr('style'));
        if ($st) {
            foreach my $h (@replacements) {
                if ($st->getPropertyValue($h->{property}) eq $h->{value}) {
                    $st->removeProperty($h->{property});
                    my $new = HTML::Element->new($h->{replacement});
                    foreach my $inner ($el->detach_content) {
                        $new->push_content($inner);
                    }
                    $el->push_content($new);
                }
            }
            $el->attr('style', $st->cssText ? $st->cssText : undef);
        }
    }
}

print $tb->as_HTML(undef, "\t");
#/usr/bin/perl
使用警告;
严格使用;
使用HTML::TreeBuilder;
使用CSS::DOM::Style;
my$html=来自内容的新内容($html);
我的@replacements=(
{property=>font-style',value=>italic',replacement=>em'},
{property=>font-weight',value=>bold',replacement=>strong'},
{property=>'text align',value=>'center',replacement=>'center'},
);
#建立一个合理的标记名列表(或者只使用sub{1})
my@nodes=$tb->look_down(sub{$\[0]->tag=~/^(p|span)$/});
对于我的$el(@nodes){
如果($el->attr('style')){
我的$st=CSS::DOM::Style::parse($el->attr('Style');
若有($st){
每小时$h(@替换){
if($st->getPropertyValue($h->{property})eq$h->{value}){
$st->removeProperty($h->{property});
my$new=HTML::Element->new($h->{replacement});
foreach my$inner($el->分离内容){
$new->push_内容($inner);
}
$el->push_内容($new);
}
}
$el->attr('style',$st->cssText?$st->cssText:undef);
}
}
}
打印$tb->as_HTML(未定义,“\t”);

为什么不在perl
perl-pi-e的/find/replace/g文件名中使用一个简单的搜索和替换呢?
对于3个替换,您可以在命令行上执行3次。@John-因为这个问题比简单的搜索和替换regex更复杂。这是我的第一反应,但是如何在内容周围包装新的HTML标记呢?完成后,HTML/应该/看起来像这样:
这里有一些随机文本。这里发生了什么并不重要,重要的是周围需要发生什么。有时并非所有文本的样式都相同。

您真正需要的是一个好的DOM解析器<代码>HTML::DOM似乎有点不成熟。你是对的,它只链接到一个页面,但我想我明白了。我来看看,谢谢。“Perl对象只是内部散列…”不是真的。Perl散列是受祝福的引用
bless{},$class
bless[]、$class
bless do{\(my$o=”“)},$class
do.OK,我给你。相应地编辑。我应该用我想出的新代码编辑我的原始问题,还是有更好的方法?在评论中添加它不会很好,而且它可能会被系统吃掉。谢谢。我猜这就是为什么我不能直接打印
$span
。这是一篇很好的文章。我最初放弃了CSS::DOM,因为我读到的CPAN页面表明它更多地用于外部CSS而不是内联(甚至是页面顶部的内部CSS)。我将在安装CSS::DOM后立即对您的代码进行测试。谢谢令人惊叹的!它起作用了,我运行了一点正则表达式来清理仍然存在的错误:

一些随机文本。什么';这里没有';它周围需要发生什么并不重要。有时并非所有文本的样式都相同。

现在,我只需要找出如何使
p
标记也能这样做,我们会很成功。现在就来看看。我使用“分离内容”的方式有问题。另外,看看如何构建一个所有允许解析的节点的列表。非常好!我将发布我的稍微调整过的版本作为新的答案,这样你就可以看到我用它做了什么。这正是我需要的!谢谢,谢谢,谢谢。另外,我不知道您是否注意到了,但是
as_HTML
似乎去掉了结尾
p
标记。我通过添加一个空的hashref(
{}
)作为第三个参数(根据HTML::TreeBuilder文档)修复了它。它不想让我回答我自己的问题P以下是代码:
#!/usr/bin/perl
use warnings;
use strict;

use HTML::TreeBuilder;
use CSS::DOM::Style;

my $html = <<HTML;
<p style="text-align:center"><span style="font-weight:bold;font-style:italic;">Some random text here. What's here doesn't matter so much as what needs to ha>
HTML

my $tb = HTML::TreeBuilder->new_from_content($html);


my @replacements = (
    { property => 'font-style', value => 'italic', replacement => 'em' },
    { property => 'font-weight', value => 'bold', replacement => 'strong' },
    { property => 'text-align', value => 'center', replacement => 'center' },
);

# build a sensible list of tag names (or just use sub { 1 })
my @nodes = $tb->look_down(sub { $_[0]->tag =~ /^(p|span)$/ });

for my $el (@nodes) {
    if ($el->attr('style')) {
        my $st = CSS::DOM::Style::parse($el->attr('style'));
        if ($st) {
            foreach my $h (@replacements) {
                if ($st->getPropertyValue($h->{property}) eq $h->{value}) {
                    $st->removeProperty($h->{property});
                    my $new = HTML::Element->new($h->{replacement});
                    foreach my $inner ($el->detach_content) {
                        $new->push_content($inner);
                    }
                    $el->push_content($new);
                }
            }
            $el->attr('style', $st->cssText ? $st->cssText : undef);
        }
    }
}

print $tb->as_HTML(undef, "\t");