0

我有一个 url 抓取器设置,它工作正常。它抓取响应标头中的文档的 url,例如:

<script type='text/javascript' language='JavaScript'>
document.location.href = 'http\x3a\x2f\x2fcms.example.com\x2fd\x2fd\x2fworkspace\x2fSpacesStore\x2f61d96949-b8fb-43f1-adaf-0233368984e0\x2fFinancial\x2520Agility\x2520Report.pdf\x3fguest\x3dtrue'
</script>   

这是我的抓取脚本。

<?php

set_time_limit(0);
$target_url = $_POST['to'];
$html =file_get_contents($target_url);

$pattern = "/document.location.href = '([^']*)'/";
preg_match($pattern, $html, $matches, PREG_OFFSET_CAPTURE, 3);

$raw_url = $matches[1][0];
$eval_url = '$url = "'.$raw_url.'";';

eval($eval_url);
echo $url;

我们必须在我们的文档管理系统中添加一个变量,所以每个文档 url 都需要在 url 的末尾加上 ?guest=true。当我们这样做时,我的抓取器返回了完整的 url 并将其附加到文件名中。所以我试图让它只抓取 url,直到它到达 /guest=true。使用此代码:

<?php

set_time_limit(0);

$target_url = $_POST['to'];
$html =file_get_contents($target_url);

$pattern = "/document.location.href = '([^']*)\x3fguest\x3dtrue'/";

preg_match($pattern, $html, $matches, PREG_OFFSET_CAPTURE, 3);

$raw_url = $matches[1][0];
$eval_url = '$url = "'.$raw_url.'";';

eval($eval_url);
echo $url;

为什么直到 ?guest=true 部分才返回 url?aka 为什么这不起作用?解决方法是什么?

4

2 回答 2

1

这就是解决方案。您将直接获得比赛,而不是分组。

set_time_limit(0);

$target_url = $_POST['to'];
$html = file_get_contents($target_url);

$pattern = '/(?<=document\.location\.href = \').*?(?=\\\\x3fguest\\\\x3dtrue)/';

preg_match($pattern, $html, $matches))

$raw_url = $matches[0];
$eval_url = '$url = "'.$raw_url.'";';

eval($eval_url);
echo $url;

你可以在这里查看结果。

您的正则表达式的问题在于您没有转义字符串 ( .and \) 中您想要捕捉文学作品的某些字符。此外,您不需要使用PREG_OFFSET_CAPTURE和偏移3. 我猜您是从本页示例中复制了这些值。

这是正则表达式模式的解释:

# (?<=document\.location\.href = ').*?(?=\\x3fguest\\x3dtrue)
# 
# Assert that the regex below can be matched, with the match ending at this position (positive lookbehind) «(?<=document\.location\.href = ')»
#    Match the characters “document” literally «document»
#    Match the character “.” literally «\.»
#    Match the characters “location” literally «location»
#    Match the character “.” literally «\.»
#    Match the characters “href = '” literally «href = '»
# Match any single character that is not a line break character «.*?»
#    Between zero and unlimited times, as few times as possible, expanding as needed (lazy) «*?»
# Assert that the regex below can be matched, starting at this position (positive lookahead) «(?=\\x3fguest\\x3dtrue')»
#    Match the character “\” literally «\\»
#    Match the characters “x3fguest” literally «x3fguest»
#    Match the character “\” literally «\\»
#    Match the characters “x3dtrue” literally «x3dtrue»

此答案已被编辑以反映问题的更新。

于 2012-09-07T22:56:26.610 回答
0

看来您的正则表达式是错误的。你添加到你的正则表达式,它从字面上\?guest=true匹配。?guest=true

在您的示例响应标头中,它以 结尾\x3fguest\x3dtrue,这是不同的。

尝试:

$pattern="/document.location.href = '([^']*)(\?|(\\x3f))guest(=|(\\x3d))true'/";

我只是替换了以下子表达式:

  • \?现在(\?|(\\x3f))是匹配?\x3f字面上的
  • = 现在(=|(\\x3d))是匹配=\x3d字面上的

这样,如果使用?or的转义十六进制表示=,它仍然会正确匹配。

于 2012-09-07T22:45:00.143 回答