【问题标题】:Fetching HTML table elements into an array将 HTML 表格元素提取到数组中
【发布时间】:2013-07-10 05:47:56
【问题描述】:

我需要从在线时间表(对于一所学校)中提取课程到一个数组中。所以我可以将数据插入我的数据库。在线时间表(url:roosters-hd.stenden.com)是这样的:

左边是时代,顶部是学生时代(Mo, Tu, We, Th, Fr)。非常基础。

每节课包含我需要获取的 6 个值。

除此之外,我还需要获取 [startDate] 和 [endDate]。时间取决于课程单元格在哪一行,以及它有多少行跨度。可以通过将列号添加到开始日期(打印在顶部)来计算日期。 所以最终数组看起来像这样:

[0] => Array
        (
            [0] => Array
                (
                    [Name] => Financiering
                    [Type] => WC
                    [Code] => DECBE3
                    [Classroom] => E2.053 - leslokaal
                    [Teacher] => Verboeket, Erik (E)
                    [Class] => BE1F, BE1B, BE1A
                    [StartDate] => 04/06/2013 08:30:00
                    [EndDate] => 04/06/2013 10:00:00
                )
                etc.

由于我缺乏获取数据的经验,我最终会得到一个效率极低且不灵活的解决方案。就像我应该使用 XML 解析器一样吗?还是正则表达式?关于如何解决这个问题的任何想法?

【问题讨论】:

  • 不要正则表达式! stackoverflow.com/a/1732454/2170192
  • 是的,不是正则表达式,正则表达式用于解析字符串,它非常强大,但仍然不应该用于这种解析。此外,您发布的链接返回 400 错误请求。最好看到现场示例,您可以将其放在 jsfiddle.net 中
  • 固定链接。我现在没有任何例子,因为我不确定我应该从哪里开始。我的意思是,获取数据的正确有效方式。

标签: php regex xml-parsing html-parsing


【解决方案1】:

正则表达式方式:

<pre><?php
$html = file_get_contents('the_url.html');

$clean_pattern = <<<'LOD'
~
  # definitions
    (?(DEFINE)
        (?<start>         <!--\hSTART\hOBJECT-CELL\h-->                    ) 
        (?<end>           (?>[^<]++|<(?!!--))*<!--\hEND\hOBJECT-CELL\h-->  )

        (?<next_cell>     (?>[^<]++|<(?!td\b))*<td[^>]*+>  ) 
        (?<cell_content>  [^<]*+                           )
    )

  # pattern
    \g<start>
        \g<next_cell>     (?<Name>      \g<cell_content>   )  
        \g<next_cell>     (?<Type>      \g<cell_content>   )
        \g<next_cell>     (?<Code>      \g<cell_content>   )

        \g<next_cell>     (?<Classroom> \g<cell_content>   )
        \g<next_cell>

        \g<next_cell>     (?<Teacher>   \g<cell_content>   )
        \g<next_cell>     
        \g<next_cell>     (?<Class>     \g<cell_content>   )
    \g<end>
~x
LOD;

preg_match_all($clean_pattern, $html, $matches, PREG_SET_ORDER);

foreach ($matches as $match) {
    echo <<<LOD
    Name: {$match['Name']}
    Type: {$match['Type']}
    Code: {$match['Code']}
    Classroom: {$match['Classroom']}
    Teacher: {$match['Teacher']}
    Class: {$match['Class']}<br/><br/>
LOD;
}

DOM/XPath 方式:

$doc = new DOMDocument();
@$doc->loadHTMLFile('the_url.html');
$xpath = new DOMXPath($doc);
$elements = $xpath->query("//*[comment() = ' START OBJECT-CELL ']");
$fields = array('Name', 'Type', 'Code', 'Classroom', 'Teacher', 'Class');
$not_needed = array(10,8,6,1,0);    
foreach ($elements as $element) {
    $temp = explode("\n", $element->nodeValue);
    foreach ($not_needed as $val) { unset($temp[$val]); }
    array_walk($temp, function (&$item){ $item = trim($item); });
    $result[] = array_combine($fields, $temp);
}   
print_r ($result);

【讨论】:

  • 我在 Rubular 中尝试了你的原始模式,但它似乎不匹配任何东西。 rubular.com/r/xwfwYKy13S.
  • @JasperJ:rubular 是用于 ruby​​ 而不是 php,您可以做的最好的测试就是在您的代码中!否则,您可以使用为 php 设计的regex.larsolavtorvik.com
  • 好吧,我傻了。我试过 preg_match_all($raw_pattern, $data, $out);数据是来自 url 的 file_get_content。但仍然没有成功(php 5.3.26)。但我会等待更新。
  • 我喜欢你的 xPath 版本。我仍然需要能够计算开始和结束日期。有没有办法获取:单元格的列名/编号、行名/编号和行跨度?
  • @JasperJ:我刚刚看到您需要开始和结束日期时间。
猜你喜欢
  • 2017-07-03
  • 1970-01-01
  • 2023-04-09
  • 1970-01-01
  • 2013-12-27
  • 1970-01-01
  • 2021-05-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多