【问题标题】:Scraping data from data.gov.uk / Regular Expression从 data.gov.uk / 正则表达式中抓取数据
【发布时间】:2016-08-07 19:35:42
【问题描述】:

我正在尝试找出我应该使用什么正则表达式来从 gov.uk 网站上抓取一些数据。

基本上,我在以下 URL 上使用 file_get_contents:

https://www.compare-school-performance.service.gov.uk/?keywords=[SCHOOL-NAME]&suggestionurn=&searchtype=search-by-name

例如 - The+Castle+School 代替 [SCHOOL-NAME]。

这将返回 4 个结果。我希望能够为返回的所有结果捕获学校 ID、学校名称和学校地址。可能会有多页结果,因此抓取所有结果很重要。

我一直在尝试使用 RegExBuddy 来执行此操作,但无法正常工作。

关于每个结果返回的数据是相当一致的如下​​:-

 <li class="document">
                <div>
                    <h3>
                        <a class="bold-small" href="/school/110182">The Castle School</a>
                    </h3>
                    <div class="comparsion-button-container">
                        <div id="JsAddRemoveError" class="optional-section no-js-hidden">
                            <p class="error-message">An error had occurred whilst trying to add or remove this school or college to comparison. Try again now or later.</p>
                        </div>
<a class="button button-comparison button-comparison-add" id="AddComparison110182" href="/addCompare/110182/searchResults/find-a-school-in-england?keywords=The+Castle+School&amp;suggestionurn=&amp;searchtype=search-by-name"
   data-js-url="/add-to-comparison-js/110182/searchResults">Add <span class="visuallyhidden">The Castle School </span>to comparison list</a>
                    </div>
                </div>

<dl class="metadata">


    <dt>Address<span aria-hidden="true">:</span></dt>
    <dd>Love Lane, Newbury, RG14 2JG</dd>

    <dt class="visuallyhidden">Phase of education<span aria-hidden="true">:</span></dt>
    <dd>Primary, Secondary and 16 to 18</dd>

        <dt>School type<span aria-hidden="true">:</span></dt>
            <dd>Special School</dd>


    <dt>Ofsted rating<span aria-hidden="true">:</span></dt>
    <dd>
        <span class="rating rating-1" aria-hidden="true">
            <span class="rating-text">
                1
            </span>
        </span>
        Outstanding
            <span class="rating-date">
                <span><span aria-hidden="true">(</span>Last inspection<span aria-hidden="true">:</span></span>
                <span>
                    <time datetime="2014-10-08">08 October 2014</time><span aria-hidden="true">)</span>
                </span>
            </span>
    </dd>


</dl>

<div style="clear: both;"></div>

每个结果都封装在一个

<li class=document">

这里可以找到学校名称和学校 ID:-

<a class="bold-small" href="/school/110182">The Castle School</a>

在本例中,学校 ID 为 110182,学校名称为 The Castle School。

地址也总是夹在:-

<dd>Love Lane, Newbury, RG14 2JG</dd>

对于返回超过 1 页结果的结果集示例,您可以使用“语法”一词

我意识到这是一个很大的问题,但我一直在尝试使用 RegExBuddy 来尝试创建正确的正则表达式,但似乎找不到正确的答案。

如果您对获取所需信息的方法有更好的了解,请告诉我。我知道他们提供他们的数据供下载,但我不想这样做,因为这会涉及存储该数据并不断更新它 - 而他们网站上的数据将始终是最新的。

谢谢。

编辑:请参阅 Jan 的回答和我的评论。非常令人印象深刻的答案。

【问题讨论】:

  • 出于兴趣,既然网站已经允许您下载原始数据,为什么还要在这里进行屏幕抓取?
  • “我知道他们提供数据供下载,但我不想这样做,因为这会涉及存储该数据并不断更新它 - 而他们网站上的数据将始终是最新的。”
  • @Resurgent 您可以每次下载数据,即不一定存储它。是否有可能每次下载数据的相关部分仍然比屏幕抓取更有效? (鉴于屏幕抓取涉及下载一大堆不相关的 HTML 以及您实际想要的数据)。也就是说,这是一种真正没有高频率变化的数据;为什么不将其存储在本地,至少在短缓存中?

标签: php regex expression screen-scraping scrape


【解决方案1】:

与往常一样,使用解析和正则表达式的组合

<?php

$url = 'https://www.compare-school-performance.service.gov.uk/?keywords=[SCHOOL-NAME]&suggestionurn=&searchtype=search-by-name';

$previous_value = libxml_use_internal_errors(TRUE);

$dom = new DOMDocument();
$dom->loadHTMLFile($url);

$xpath = new DOMXPath($dom);

# regex part
$regex = '~(?P<id>\d+)$~';

# here comes the main part
$schools = $xpath->query("//ul[@class = 'school-results-listing']//li");
foreach($schools as $school) {
    $name = $xpath->query(".//h3/a/text()", $school)->item(0)->nodeValue;
    preg_match($regex, $xpath->query(".//h3/a/@href", $school)->item(0)->nodeValue, $match);
    $id = $match["id"];

    $address = $xpath->query(".//dl[@class = 'metadata']//dd/text()", $school)->item(0)->nodeValue;
    echo "Name: {$name}, ID: {$id}, Address: {$address} \n"; 
}
libxml_clear_errors();
libxml_use_internal_errors($previous_value);

?>

这会加载 DOM 中的文档,遍历它并借助 id 部分的简单正则表达式提取所需信息。
请勿在直接HTML

【讨论】:

  • 好的。这是太棒了。只需要这样:- $address = $xpath->query(".//dl[@class= 'metadata']//dd/text()", $school)->item(0)->节点值;然后它工作正常。非常令人印象深刻。
猜你喜欢
  • 2014-07-06
  • 2013-07-30
  • 1970-01-01
  • 1970-01-01
  • 2013-08-21
  • 2011-04-21
  • 1970-01-01
  • 1970-01-01
  • 2021-02-19
相关资源
最近更新 更多