【问题标题】:Getting Matched HTML Value with Regex使用正则表达式获取匹配的 HTML 值
【发布时间】:2012-07-02 13:31:34
【问题描述】:

好的,我知道我不应该使用正则表达式来解析 HTML,因为它不是很可靠,不是 100% 安全等。但是,这只是正则表达式的学习练习。

所以我的例子使用了 bbc 网站http://www.bbc.co.uk/sport/football/premier-league/table

项目正在解析第一个表的 tbody。我正在尝试进行搜索,以便只返回与搜索值匹配的元素。例如,给定搜索“manc”,我想要曼彻斯特城和曼彻斯特联队的 tr 标签(从 url 匹配)。

到目前为止,我所拥有的是<tr\b[^>]*>(.*?)manc(.*?)</tr>,但是这从第一个 tr 到 man city 之后的结束 tr 匹配,然后返回 man utd 的预期结果。谁能指出我在这个正则表达式上哪里出了问题。

编辑:来源(修剪)

<tbody id="trc-20-118996114-3">
  <tr id="team-138824012" class="team first">
    <td class="statistics"></td>
    <td class='position'>
      <span class='moving-up'>Moving up</span>
      <span class='position-number'>1</span>
    </td>
    <td class="team-name">
      <a href='http://www.bbc.co.uk/sport/football/teams/arsenal'>Arsenal</a>
    </td>
    <td class="played">0</td>

    <td class="home-won">
      <span>0</span>
    </td>
    <td class="home-drawn">0</td>
    <td class="home-lost">0</td>
    <td class="home-for">0</td>
    <td class="home-against">0</td>
    <td class="away-won">
      <span>0</span>
    </td>
    <td class="away-drawn">0</td>
    <td class="away-lost">0</td>
    <td class="away-for">0</td>
    <td class="away-against">0</td>
    <td class="goal-difference">0</td>
    <td class="points">0</td>
    <td class="last-10-games">
      <ol>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="loss" title="Loss">
          <span>Loss</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="loss" title="Loss">
          <span>Loss</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win last" title="Win">
          <span>Win</span>
        </li>
      </ol>
    </td>
    <td class="status">
      <a class="report" href="http://www.bbc.co.uk/sport/0/football/17973141">Report</a>
    </td>
  </tr>
  <tr id="team-137316633" class="team">
    <td class="statistics"></td>
    <td class='position'>
      <span class='moving-up'>Moving up</span>
      <span class='position-number'>2</span>
    </td>
    <td class="team-name">
      <a href='http://www.bbc.co.uk/sport/football/teams/aston-villa'>Aston Villa</a>
    </td>
    <td class="played">0</td>

    <td class="home-won">
      <span>0</span>
    </td>
    <td class="home-drawn">0</td>
    <td class="home-lost">0</td>
    <td class="home-for">0</td>
    <td class="home-against">0</td>
    <td class="away-won">
      <span>0</span>
    </td>
    <td class="away-drawn">0</td>
    <td class="away-lost">0</td>
    <td class="away-for">0</td>
    <td class="away-against">0</td>
    <td class="goal-difference">0</td>
    <td class="points">0</td>
    <td class="last-10-games">
      <ol>
        <li class="loss" title="Loss">
          <span>Loss</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="loss" title="Loss">
          <span>Loss</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="loss" title="Loss">
          <span>Loss</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="loss" title="Loss">
          <span>Loss</span>
        </li>
        <li class="loss last" title="Loss">
          <span>Loss</span>
        </li>
      </ol>
    </td>
    <td class="status">
      <a class="report" href="http://www.bbc.co.uk/sport/0/football/17973120">Report</a>
    </td>
  </tr>
  <tr id="team-137318151" class="team">
    <td class="statistics"></td>
    <td class='position'>
      <span class='moving-down'>Moving down</span>
      <span class='position-number'>7</span>
    </td>
    <td class="team-name">
      <a href='http://www.bbc.co.uk/sport/football/teams/manchester-city'>Man City</a>
    </td>
    <td class="played">0</td>

    <td class="home-won">
      <span>0</span>
    </td>
    <td class="home-drawn">0</td>
    <td class="home-lost">0</td>
    <td class="home-for">0</td>
    <td class="home-against">0</td>
    <td class="away-won">
      <span>0</span>
    </td>
    <td class="away-drawn">0</td>
    <td class="away-lost">0</td>
    <td class="away-for">0</td>
    <td class="away-against">0</td>
    <td class="goal-difference">0</td>
    <td class="points">0</td>
    <td class="last-10-games">
      <ol>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="loss" title="Loss">
          <span>Loss</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="win last" title="Win">
          <span>Win</span>
        </li>
      </ol>
    </td>
    <td class="status">
      <a class="report" href="http://www.bbc.co.uk/sport/0/football/17973148">Report</a>
    </td>
  </tr>
  <tr id="team-137318152" class="team">
    <td class="statistics"></td>
    <td class='position'>
      <span class='moving-down'>Moving down</span>
      <span class='position-number'>8</span>
    </td>
    <td class="team-name">
      <a href='http://www.bbc.co.uk/sport/football/teams/manchester-united'>Man Utd</a>
    </td>
    <td class="played">0</td>

    <td class="home-won">
      <span>0</span>
    </td>
    <td class="home-drawn">0</td>
    <td class="home-lost">0</td>
    <td class="home-for">0</td>
    <td class="home-against">0</td>
    <td class="away-won">
      <span>0</span>
    </td>
    <td class="away-drawn">0</td>
    <td class="away-lost">0</td>
    <td class="away-for">0</td>
    <td class="away-against">0</td>
    <td class="goal-difference">0</td>
    <td class="points">0</td>
    <td class="last-10-games">
      <ol>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="loss" title="Loss">
          <span>Loss</span>
        </li>
        <li class="draw" title="Draw">
          <span>Draw</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="loss" title="Loss">
          <span>Loss</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win" title="Win">
          <span>Win</span>
        </li>
        <li class="win last" title="Win">
          <span>Win</span>
        </li>
      </ol>
    </td>
    <td class="status">
      <a class="report" href="http://www.bbc.co.uk/sport/0/football/17973162">Report</a>
    </td>
  </tr>
</tbody>

【问题讨论】:

  • 为什么投反对票 :(?需要学习以备将来参考
  • 不确定。可能是因为使用 RegEx 解析 HTML 是一个非常常见的问题。在大多数情况下,需要一个 DOM 解析器,例如 JavaScript 的 DOMParser,而不是通过正则表达式摆弄 HTML 字符串。您能否在问题中包含源代码的相关部分,而不是链接到易变的站点?这样一来,即使 BBC 决定删除该页面,该问题仍然具有相关性。
  • @RobW 添加了源代码的修剪版本

标签: c# html regex


【解决方案1】:

问题是,你的正则表达式太宽泛了。看看你要的是什么:

<tr\b[^>]*>(.*?)manc(.*?)</tr>

让我们稍微简化一下。

<tr>.*?manc.*?</tr>

所以你说,好吧。我需要匹配一个 tr,然后是 anything,然后是 manc,然后是 ANYTHING,然后是结束 tr。所以。当然会发生的是正则表达式从第一个 tr 开始并且正常。我有一个 tr 让我继续匹配,直到找到 manc。与此同时,您可能刚刚通过了一堆other tr。但是你的正则表达式不在乎。

试试这个:

<tr>(?:(?!</tr>).)*manc.+?</tr>

或者,我猜在你的例子中:

<tr\b[^>]*>(?:(?!</tr>).)*manc.+?</tr>

【讨论】:

  • 您好,感谢您的回答,它适用于 manc,是否有任何方法可以在未指定搜索的情况下(因此 &lt;tr\b[^&gt;]*&gt;(?:(?!&lt;/tr&gt;).)*.+?&lt;/tr&gt;)返回所有结果。目前我发现当这样运行时,前两个 tr 元素作为单个匹配返回
  • 这很简单:]*>.+?
  • 抱歉,是否可以在一个正则表达式中使用?
  • 你的意思是你不能有一个 if-else 语句来选择一个正则表达式?
  • 嗯...我不认为你可以。这真的没有任何意义。在一种情况下,您说匹配任何 TR,而在另一种情况下,您说匹配看起来像这样的 TR。如果您将它们与交替运算符结合使用,那么您总是会匹配任何东西。我明白学习练习的重点,但有时学习练习应该告诉你什么时候不应该尝试某事。 :)
【解决方案2】:

REGEX 不适合这种情况,因为它不是为解析器而设计的。除非情况非常宽容,尤其是在 JavaScript(它有一个相当原始的 REGEX 实现)中,它无法确定哪些开始标签与哪些结束标签匹配。

首先,我们需要使用[\s\S] 而不是.,因为后者不能多行工作,因为它不匹配空白字符,而且您提到的表格的HTML 是多行的。前者会,因为它是一个匹配所有空间和非空间的范围 - 即所有东西。

考虑到这一点,您可能会想这样做:

/<tr\b[^>]*?>[\s\S]*?manc[\s\S]*?<\/tr>/gi

...即获取所有提及字符串 'manc' 的行。

采用以下简化的 HTML:

<table>
    <tr>
        <td>Notts County</td>
    </tr>
    <tr>
        <td>Manchester United</td>
    </tr>
    <tr>
        <td>Arsenal</td>
    </tr>
</table>

...上面的模式将匹配

<tr>
    <td>Notts County</td>
</tr>
<tr>
    <td>Manchester United</td>
</tr>

这是合乎逻辑的。 REGEX 模式从开头开始,找到开头tr(诺茨县),并询问是否在不确定数量的可选字符之后找到了字符串“Manc”。是的。

当然,问题在于,在寻找“Manc”时,它不知不觉地越过了tr 边界进入下一行,因为我们的[\s\S]*? 模式允许它这样做。

我们无法阻止这种情况,因为 REGEX 不允许您对序列求反 - 只能对某个范围内的字符进行求反(否定的前瞻和后瞻断言除外)。

简而言之,无论如何都要学习正则表达式,但你选择了一个很难开始的字符串:)

【讨论】:

    猜你喜欢
    • 2015-09-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-07-24
    • 1970-01-01
    • 2011-02-17
    • 1970-01-01
    相关资源
    最近更新 更多