HTML 页面中的模式匹配

Pattern Match in an HTML Page

我无法对需要从中挖掘数据的页面使用 preg_match。在 $url 上获取内容通常会输出多个字符串,如下所示

https://www.zigsaw.in/companies-detail/AU-Small-Finance-Bank-Ltd/65344.html

这些字符串通常可以包含小字符、大字符、/、(、)、- 等。我想提取数据

  1. 在"company-detail/"
  2. 之后
  3. 在“.html”之前

我用过的代码如下

$contents=file_get_contents($url);
$pattern='/\b(https://www.zigsaw.in/companies-detail/)\b+[a-zA-Z0-9.-()]+\b(.html)\b/';
preg_match_all($pattern, $contents, $matches);
var_dump($matches);

但是,上面的代码没有获取

的预期结果

AU-Small-Finance-Bank-Ltd/65344.html

& 同样

TLDR:

使用这个:\bwww\.zigsaw\.in\/companies-detail\/\K[^\/]+\/[^\/]+(?=\.html)

Demo

解释:

你的正则表达式有几个问题

  • 正则表达式通常由 '/' 字符分隔,因此如果您使用它们,则需要对这些字符进行转义。例如,http:// 应该是 http:\/\/
  • 虽然不会出现错误,但您应该将点 . 转义为 \.,因为点表示除换行之外的任何字符。所以这里 www. 你可能指的是一个字面上的点:www\.
  • 你有这样的结构:\b+ 这是错误的。 \b 表示裸词,+ 表示重复一次或多次。这种组合没有意义。您可以通过将 + 转义为文字 +: \+ 来修复错误,但是,由于我认为这对您的正则表达式完全没有帮助,所以我会简单地删除它们
  • [a-zA-Z0-9.-()] 上,你应该将最后一个 - 换成 \.,因为破折号用于指定范围(如 a-z)。另一种选择是像这样把它放在最后:[a-zA-Z0-9.()-]

通过上述修复,您将获得:\b(https:\/\/www\.zigsaw\.in\/companies-detail\/)[a-zA-Z0-9.()-]+\b(.html)\b 但仍然不匹配。那是因为字符 class [a-zA-Z0-9.()-] 不允许条 / 出现。

所以在这里,https://www.zigsaw.in/companies-detail/Foo-BAR-Bank/12345.html 当您匹配 https://www.zigsaw.in/companies-detail/Foo-BAR-Bank 时,您不能 "go on" 匹配,稍后您期望找到 .html,这是错误的。所以正则表达式失败了。

您通过向 class 添加一个条来解决这个问题,如下所示:

\b(https:\/\/www\.zigsaw\.in\/companies-detail\/)[a-zA-Z0-9.()\/-]+\b(.html)\b

或者您可以只使用:\b(https:\/\/www\.zigsaw\.in\/companies-detail\/)[^\/]+\/[^\/]+\b(.html)\b,它将 class 更改为 [^\/]+\/[^\/]+,这意味着任何不是竖线的字符,重复一次或多次,竖线,然后任何不是竖线的字符重复一次或多次。

我们还删除了 .html 之前的 \b,因为它没有添加任何内容。

现在你遇到了只匹配你感兴趣的东西的问题。你可以像这样添加一个捕获组 \b(https:\/\/www\.zigsaw\.in\/companies-detail\/)([^\/]+\/[^\/]+)(.html)\b 并恢复第二组。

但是你也可以不捕获组来做到这一点:

\K我们将忽略所有之前匹配的数据。通过前瞻,我们 'match without matching'(我们只是检查下一个字符的一些模式,我们将它用于 \.html

所以你可以使用:

\bwww\.zigsaw\.in\/companies-detail\/\K[^\/]+\/[^\/]+(?=\.html)