0

概述

我目前正在尝试为可以在此页面中找到的站点编写一个解析器。

我已经尝试过 XPath(我非常擅长),但我在尝试达到预期结果时失败了,所以我从昨天开始就一直在尝试使用正则表达式。

我的目标

我的目标是将这个 html 拆分为多个片段,每个片段都包含一个课程的数据。

例如:"AF - Bacharelado em Artes Visuais"是课程名称,科目可以在蓝色表格中找到,直到08º Semestre: 24 Créditos

之后,您可以看到"AG - Licenciatura em Artes - Artes Visuais",这是一个新课程的开始,等等。

这个页面只有两门课程,但是这个可以有两个以上。

正则表达式问题

我的一个朋友帮了我一个忙,发现使用这种模式和选项可以达到课程的名称。这是一些代码:

// Creating Regular Expression to find name of courses
Regex regex = new Regex ("<p><br><b><font face=\"Arial,Helvetica\"><font color=\"#000099\"><font size=-1>(.+?)</font></font></font></b>", RegexOptions.Singleline);

int startIndex = 0;
while (regex.IsMatch (auxHtml, startIndex))
    {
        // Checking name of the course and saving it's offset
        int index         = regex.Match(auxHtml, startIndex).Groups[1].Index;
        string courseName = regex.Match(auxHtml, startIndex).Groups[1].Value;
    } 

问题

由于我可以找到课程的名称和偏移量(索引),理论上,我可以将 Html 拆分为多个片段,其中每个片段仅包含与单个课程相关的数据。

这是我用来尝试的代码。

  • htmlPages 是一个字符串列表
  • auxHtml 是 WebRequest 检索到的 HtmlPage

代码

// Creating Regular Expression to find name of courses
Regex regex = new Regex ("<p><br><b><font face=\"Arial,Helvetica\"><font color=\"#000099\"><font size=-1>(.+?)</font></font></font></b>", RegexOptions.Singleline);

int startIndex = 0;
while (regex.IsMatch (auxHtml, startIndex))
{
    // Checking name of the course and saving it's offset
    int index         = regex.Match(auxHtml, startIndex).Groups[1].Index;
    string courseName = regex.Match(auxHtml, startIndex).Groups[1].Value;

    // Adding name of the course and offset to dictionary
    courseIndex.Add (courseName,index);
    startIndex        = regex.Match(auxHtml, startIndex).Groups[1].Index;

    // Splitting HTML Page
    if (regex.IsMatch(auxHtml, startIndex))
    {
        int endIndex = regex.Match (auxHtml, startIndex).Groups[1].Index;
        endIndex  = endIndex - startIndex;
        htmlPiece = auxHtml.Remove(startIndex, endIndex);
    }

    htmlPages.Add(auxHtml);
}

我不知道为什么,但是索引有点乱。

第二个课程名称的索引是 8022,但是,如果我尝试:

auxHtml.Substring(0,8022) 

它为我提供了在下一门课程名称之前结束的 html 的一部分。

我在这里想念什么?

这不就是一个Group的“Index”属性,是html页面中pattern开始的索引吗?

4

4 回答 4

5

虽然您可能几乎可以使用 RegEx 实现您正在寻找的东西,但它肯定会很困难。

正则表达式不是这项工作的正确工具。使用 XML 解析器解析 HTML 会好很多。那是因为 HTML(和一般的 XML)标记不是常规语言 - 因此正则表达式在这种情况下不是很有用。

您应该查看 System.Xml.XmlDocument 类。

于 2012-07-27T14:11:17.670 回答
4

您不应该使用正则表达式来解析 HTML。真正的正则表达式是无能为力的,扩展的正则表达式也不适合它。您应该使用现有的解析库来处理 HTML,如果您必须自己进行处理,您应该将您的解决方案基于上下文无关语言,而不是常规语言。

于 2012-07-27T14:11:53.707 回答
3

不要对 HTML 使用 Regex,使用Html Agility Pack以允许您在 Html 上使用 XPath。

问题是 HTML 不是一种行为良好的语言,Regex 解析的规则有太多例外。Html Agility Pack 等库专门用于解决此问题。

于 2012-07-27T14:12:08.857 回答
1

即使没有为这种情况指定正则表达式,我也使用了它,并且可以解决我的问题。

我不会复制任何代码,因为代码很大,但我会解释我做了什么。

我使用这个正则表达式来查找课程名称

Regex regex = new Regex ("<p><br><b><font face=\"Arial,Helvetica\"><font   color=\"#000099\"><font size=-1>(.+?)</font></font></font></b>", RegexOptions.Singleline);`

之后我设法找到每个课程名称的偏移量

获取每个课程名称的偏移量后,我将 Html 拆分为段,其中段的开头是课程名称之前的偏移量,结尾是 NEXT 课程名称之前的偏移量,或文件的结尾该课程的案例是html中的最后一个。

对于那些感兴趣的人,这是我的实现代码

我希望这可以帮助像我这样尝试解析非格式良好的 html 的人。

现在,对于那些说正则表达式无法执行此任务的人,请花点时间阅读我的代码,它可能会改变您的想法。

于 2012-07-27T19:10:35.353 回答