Php 正则表达式从HTML中的标记获取特定信息

Php 正则表达式从HTML中的标记获取特定信息,php,html,regex,Php,Html,Regex,我有一个HTML页面,其标记代码如下: <a href="#!/series/3078/series-name"> <span class="title">This is series # 1</span> <span class="info">bla bla bla</span> </a> <a href="#!/series/3079/series-name-2"> <span class

我有一个HTML页面,其标记代码如下:

<a href="#!/series/3078/series-name">
  <span class="title">This is series # 1</span>
  <span class="info">bla bla bla</span>
</a>

<a href="#!/series/3079/series-name-2">
  <span class="title">This is series # 2</span>
  <span class="info">bla bla bla</span>
</a>

<a href="#!/series/3080/series-name-3">
  <span class="title">This is series # 3</span>
  <span class="info">bla bla bla</span>
</a>

我需要得到“/series/”后面的数字和类“title”的内部范围的文本

如何在PHP上使用正则表达式实现这一点


感谢您的帮助

如果您的标记比您发布的代码段长得多,那么regex就不是一个好办法,因为它在计算上非常昂贵

(无论如何,您都不能用正则表达式完全解析XML)

我的建议是,使用一个可以遍历它所表示的树结构的语法来解析标记。这将允许您轻松获取所需的数据

如果
href
属性总是看起来像
#/series/XXXX/series-name-2
然后通过简单的字符串解析访问
XXXX

与Pi一样简单 下面是一个小Perl程序,它演示了在非常规则和已知组成的HTML小块上使用正则表达式是多么容易

#/usr/bin/env perl
$uz=do{local$/;};
而(m!/series/(\d+)!g){
打印“系列$1:”;
如果(m!(**?)g){
打印$1;
}
打印“\n”;
}    
__结束__

运行时,该程序将打印出:

3078系列:这是第1系列
3079系列:这是第2系列
3080系列:这是第3系列
看看这有多容易?没什么

同样的模式也适用于PHP,因为我没有做任何只有Perl而不是PCRE做的事情


另一方面 构建将打乱此特定方法的输入并不太难。再一次,正如我所展示的,在其他地方,也不难补偿这一点

人们总是使用文本编辑器编辑HTML。这是完全正常的。当他们这样做时,他们使用正则表达式。当一个程序做同样的事情时,它不像是一个被祝福,另一个被诅咒。在一个不是文本编辑器的不同程序中执行与在文本编辑器中完全相同的操作没有错

然而,除了最简单的事情(比如这里的这个问题,算起来很简单)之外,其他所有事情都有一个折衷的办法,大多数人问怎么做都不能做到。关于这个悖论,我有一个较长的讨论。

这里:(编辑!

preg\u match\u all($links,'/\/series\/([\d]+)\/.*(.*?)/ism',$matches);
var_dump($matches);

希望有帮助。不过,我建议用PHP查看DOMDocument。我认为这将是一个更清洁的解决方案。正则表达式往往是丑陋而缓慢的。

正则表达式是否适合此作业取决于作业的实际内容。如果您有一个很大的HTML页面或一组HTML页面,并且希望从中提取信息,那么正则表达式可能是一个不错的选择。然而,如果您的输入不在您的控制之下,那么regex根本不是您想要的


无论如何,使用PHP实现这一点的正确方法就是使用解析html,然后使用从中得到的
DOMDocument
getElementsByTagName
并对其进行迭代。如果你喜欢,甚至可以使用XPath。对于解析HTML而言,这永远是一个比正则表达式更健壮的工具,除非您实际上已经用正则表达式编写了HTML解析器。

@tchrist我不同意您的看法。HTML上的正则表达式基本上有一个根本不起作用的用途,即验证用户输入的HTML以搜索
标记等(cf“samy是我的英雄”),还有一个他们非常擅长的用途,即从HTML页面中获取列表等。但是当您想从DOM中获取信息时,如本例所示(要做到这一点,我不知道PHP有什么用。@cha0site你可以尊重他人,但你仍然是错的。没有任何理由不在HTML上使用文本编辑器。人们总是这样做。@Qtax:是的。但是Stackoverflow只能提供过时的、技术上不过分的c,这不是有点尴尬吗解释新手替代方案的笑话页面是否正确?@tchrist我认为这里合适的拉丁语是Quod-licet-Iovi,非licet-bovi。显然,你可以用正则表达式解析任何东西。你确实在上面写了这本书。然而,当有人问“我试图用正则表达式解析HTML,但无法理解”,正确的答案是“好的,不要这样做,用解析器代替”,而不是在正则表达式中添加另一个特例。因为HTML解析器不太常见,但几乎和正则表达式库一样常见,而且它们非常擅长解析HTML。@tchrist“如果它们可以在文本编辑器中使用正则表达式,那么它们可以在文本编辑器之外使用相同的正则表达式”-不,这是错误的。解决方案在一个上下文中是合适的,但在另一个上下文中并不正确。文本编辑器是一个上下文,您在其中查看一些非常特定的垃圾并希望将其转换为所需的垃圾。PHP脚本位于Web服务器上,只处理垃圾,而无需手动处理input、 是另一种情况。正则表达式适用于第一种情况,如果你知道一些你将得到的输入,则适用于第二种情况。但一般来说?是的,如果你喜欢用正则表达式编写你自己的“解析器”,这并不难。而且,处理“不太有效的HTML”的所有细节也很有趣解析。@Qtax我确实喜欢这样。但是提供的问题规范是非常有限的,它的正则表达式解决方案非常简单和明显,并且完全足够了。去写一些经过大量工程设计的庞然大物,去做一个完整的解析来建立整个树,只为了做我上面展示的简单提取HTML的发明并没有淘汰像
grep
vi
这样的长期存在的工具,假装不这样做对所有人都是有害的。解决手头的问题,不要过度设计,你就可以和y共进晚餐了
preg_match_all($links, '/\/series\/([\d]+)\/.*?<span class="title">(.*?)<\/span>/ism', $matches);

var_dump($matches);