0

我正在尝试从网站上获取多个事件。事件有一个常规的格式

... EVENT TITLE & LINK ... START DATE ... END DATE ... <span class="location">LOCATION</span> ...

其中“...”是一些带有样式信息和换行符的 html 标签。我想从这些事件字符串中提取 LINK、START DATE、END DATE 和 LOCATION。由于周围的 html 代码“...”的格式是完全规则的,因此抓取这四条信息很容易:我匹配周围的标签并提取我想要的部分,例如:

'|...<abbr class="dtstart">(.{10}).*?</abbr>...|s'

其中“(.{10})”是开始日期。

问题是位置,因为某些事件列出了位置,而其他事件没有列出,因此在某些事件中跨度标签 <span class="location">LOCATION</span> 存在,而在其他事件中它只是丢失了.

所以我的问题是:

如何匹配 LOCATION?

如果我尝试

preg_match_all('|...<span class="location">(.+?)</span>...|s', $contents, $matches, PREG_SET_ORDER);

在没有位置的事件上,它与该事件不匹配(但我得到了具有位置的事件的位置)。另一方面,如果我尝试

preg_match_all('|...(?:<span class="location">(.+?)</span>)...|s', $contents, $matches, PREG_SET_ORDER);

在任何情况下,该代码都匹配所有事件,但 LOCATION(即使它存在)不是我的 $matches 的一部分。

那么如何匹配常规但可选子字符串的不规则部分?

谢谢!

编辑(作为回答 zigdon 的问题):

问题是 LOCATION 必须与其他事件数据相匹配。想象一下这就是我想要的结果:“正则表达式协会大会(链接到网站),4 月 7 日至 4 月 10 日,柏林”和“在线教程(链接到网站,5 月 9 日”。第二个活动没有位置,但是第一个事件的位置必须与标题,链接和日期匹配。这是我要从中抓取事件的页面的链接,您可以查看源代码以了解问题:https ://www.fs-psycho.uni-tuebingen.de/events/previous - 目前我抓住事件

preg_match_all('|<dt class="vevent">\s*?<span class="summary">\s*?(<a href=".+?</a>)\s*?</span>\s*?<span class="documentByLine">\s*?<span>(?:von )?<abbr class="dtstart" title=".{0,30}">(.{10}).{0,6}</abbr>.{5,100}<abbr class="dtend" title=".+?">(.{0,10}).{5,6}</abbr></span>\s*?(?:<span>— <span class="location">(.*?)</span>,</span>)?\s*?</span>\s*?</dt>|', $contents, $matches, PREG_SET_ORDER);

这行得通,但我对此不满意,因为正如答案中提到的,使用“野生代码”(来自不是我自己的网站)标签之间可能会发生任何事情。我更喜欢只匹配事件部分的直接周围并且将中间的任何内容都非常开放的解决方案,即“。*?| s”。

4

1 回答 1

1

使用正则表达式来解析 HTML(或任何实际标记)通常是一个非常糟糕的主意。大多数语言都提供了一个库,可以实际解析 HTML,并允许您获取所需的特定元素,而无需尝试将标签与正则表达式匹配。也许,因为看起来你可能正在使用 PHP,你可以看看这样的东西?http://simplehtmldom.sourceforge.net/

另请参见RegEx 匹配打开的标签,XHTML 自包含标签除外

于 2012-04-09T21:34:35.103 回答