首页 > 解决方案 > 在 Perl 中使用正则表达式从 HTML 中提取 img 标签

问题描述

我需要从 url 中提取验证码并用 Tesseract 识别它。我的代码是:

#!/usr/bin/perl -X
###
$user = 'user'; #Enter your username here
$pass = 'pass'; #Enter your password here
###
#Server settings
$home = "http://perltest.adavice.com";
$url = "$home/c/test.cgi?u=$user&p=$pass";
###Add code here!
#Grab img from HTML code
#if ($html =~ /<img. *?src. *?>/)
#{
#    $img1 = $1;
#}
#else 
#{
#    $img1 = "";
#}
$img2 = grep(/<img. *src=.*>/,$html);
if ($html =~ /\img[^>]* src=\"([^\"]*)\"[^>]*/)
{
    my $takeImg = $1;
    my @dirs = split('/', $takeImg);
    my $img = $dirs[2];
}
else
{
    print "Image not found\n";
}
###
die "<img> not found\n" if (!$img);
#Download image to server (save as: ocr_me.img)
print "GET '$img' > ocr_me.img\n";
system "GET '$img' > ocr_me.img";
###Add code here!
#Run OCR (using shell command tesseract) on img and save text as ocr_result.txt
system("tesseract ocr_me.img ocr_result");
print "GET '$txt' > ocr_result.txt\n";
system "GET '$txt' > ocr_result.txt";
###
die "ocr_result.txt not found\n" if (!-e "ocr_result.txt");
# check OCR results:
$txt = 'cat ocr_result.txt';
$txt =~ s/[^A-Za-z0-9\-_\.]+//sg;
$img =~ s/^.*\///;
print `echo -n "file=$img&text=$txt" | POST "$url"`;

如您所见,我正在尝试提取 img src 标签。这个解决方案对我不起作用 ($img1)在 perl 脚本中使用 shell 命令 tesseract 来打印文本输出。我还使用了该解决方案的采用版本($img2)如何在 Perl 中从 HTML 中提取 URL 和链接文本?.

如果你需要该页面的 HTMLcode,这里是:

<html>
<head>
<title>Perl test</title>
</head>
<body style="font: 18px Arial;">
<nobr>somenumbersimg src="/JJ822RCXHFC23OXONNHR.png" 
somenumbers<img src="/captcha/1533030599.png"/>
somenumbersimg src="/JJ822RCXHFC23OXONNHR.png" </nobr><br/><br/><form method="post" action="?u=user&p=pass">User: <input name="u"/><br/>PW: <input name="p"/><br/><input type="hidden" name="file" value="1533030599.png"/>Text: <input name="text"></br><input type="submit"></form><br/>
</body>
</html>

我得到了找不到图像的错误。我的问题是错误的正则表达式,我认为。我无法安装任何模块,例如 HTTP::Parser 或类似的

标签: htmlregexperlparsing

解决方案


除了在 HTML 上使用正则表达式不太可靠之外,您在以下代码中的正则表达式将无法工作,因为它缺少捕获组,因此$1不会被分配值。

if ($html =~ /<img. *?src. *?>/)
{
    $img = $1;
}

如果要使用正则表达式提取部分文本,则需要将该部分放在括号内。例如:

$example = "hello world";
$example =~ /(hello) world/;

这会将 $1 设置为“你好”。

正则表达式本身没有多大意义——你有“。*?”,它会匹配任何后跟 0 个或多个空格的字符。这是“。*”的错字吗?它将匹配任意数量的字符,但不像“。*”那样贪婪,因此当它找到正则表达式的下一部分匹配时会停止。

这个正则表达式可能更接近您正在寻找的内容。它将匹配具有以“/captcha/”开头的 src 属性的第一个 img 标签,并将图像 URL 存储在$1

$html =~ m%<img[^>]*src="(/captcha/[^"]*)"%s;

分解它是如何工作的。“m%....%”只是“/.../”的另一种说法,它允许您在正则表达式中放置斜杠,而无需转义它们。"[^>]*" 将匹配除“>”之外的任何字符的零个或多个 - 所以它不会匹配标签的结尾。并且 "(/captcha/[^"]*)" 正在使用捕获组来抓取双引号内将成为 URL 的任何内容。它还在末尾使用 "/s" 修饰符,这将被$html视为只是一长行文本并忽略\n其中可能不需要的任何内容,但是如果 img 标签被拆分为多行,它仍然可以工作。


推荐阅读