当我不知道子域时,如何替换 HTML 中的域名?

Zip*_*970 1 regex perl

我有标量中的 HTML 代码。HTML 代码可以包含我想要替换的某个域的 URL。例如:

my $code = <<ENDCODE;
  <img src="http://server1.olddomain.com/image1.jpg">
  <img src="http://server5.otherdomain.com/image2.jpg">
  <img src="http://server2.olddomain.com/image3.jpg">
ENDCODE
Run Code Online (Sandbox Code Playgroud)

URL 的服务器部分可以是任何内容(因此不一定是“www”)。我希望将所有指向 olddomain.com 的图像 URL 替换为 newdomain.com,但前提是该图像存在于 newdomain.com 上。所以我不能简单地进行直接替换,而是需要调用一个函数(进行必要的检查)。所以我想我会做这样的事情:

$code =~ s/src=\"(.+?\.olddomain\.com\/.+?)\"/URLReplace($1)/gsie;
Run Code Online (Sandbox Code Playgroud)

URLReplace 是一个执行所有检查并在必要时替换 URL 的函数。问题是正则表达式找到两个匹配项:

http://www.olddomain.com/image1.jpg
Run Code Online (Sandbox Code Playgroud)

http://www.otherdomain.com/image2.jpg">\n<img src="http://www.olddomain.com/image3.jpg
Run Code Online (Sandbox Code Playgroud)

问题当然是第一个.+?捕获了直到下一个“.olddomain.com”的所有内容,在第二个匹配中,它是 .olddomain.com http://www.somedomain.com/image2.jpg">\n<img src="http://www

那么我该如何解决这个问题呢?

bri*_*foy 6

您可以使用 DOM 来更改 HTML,而不是使用正则表达式。Mojo::DOM 支持 CSS 选择器来匹配属性中的子字符串。找到要更改的节点后,您可以使用 Mojo::URL(或任何 URI 库)的功能来替换主机名:

use v5.10;
use Mojo::DOM;
use Mojo::URL;

my $code = <<~'ENDCODE';
  <img src="http://server1.olddomain.com/image1.jpg">
  <img src="http://server5.otherdomain.com/image2.jpg">
  <img src="http://server2.olddomain.com/image3.jpg">
ENDCODE

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

my $old = ".olddomain.com";
$dom->find( "img[src*=$old]" )
    ->each( sub {
        my $url = Mojo::URL->new($_->attr('src'));
        return unless $url->host =~ m/\Q$old\E\z/;
        $url->host(  $url->host =~ s/\Q$old\E\z/\.newdomain.com/r );
        $_->attr( src => $url );
        } )
    ;

say $dom;
Run Code Online (Sandbox Code Playgroud)

输出显示域的选择性更新:

<img src="http://server1.newdomain.com/image1.jpg">
<img src="http://server5.otherdomain.com/image2.jpg">
<img src="http://server2.newdomain.com/image3.jpg">
Run Code Online (Sandbox Code Playgroud)

诀窍在于每个阶段都会限制效果,这样您就不会遇到不想更改的文本。您知道您有img带有 a 的标签src,其中包含您想要的子字符串,然后您知道您只处理该src值,然后您知道您只处理hostURL 的部分。

我在Mojolicious Web UserAgents中有大量 DOM 解析和修改的示例。