2

我正在通过 last.fm 的 API 为我的 mashup 获取大量用户数据。我每周都会这样做,因为我必须收集听力数据。

我通过他们的 REST API 和 XML 获取数据:更具体地说simplexml_load_file()

剧本花的时间长得可笑。对于大约 2 300 个用户,该脚本需要 30 分钟才能仅获取艺术家的姓名。我现在必须修复它,否则我的托管公司将关闭我。我已经排除了所有其他选项,是 XML 减慢了脚本的速度。

我现在必须弄清楚 last.fm 是否有一个缓慢的 API(或者在没有他们告诉我们的情况下限制调用),或者 PHP 的 simplexml 是否实际上相当慢。

我意识到的一件事是 XML 请求获取的数据比我需要的要多得多,但我不能通过 API 限制它(即只给我 3 个波段的信息,而不是 70 个波段)。但是“大”XML 文件只能达到大约 20kb。难道是这样,这会减慢脚本的速度吗?必须为 2300 个用户中的每个用户加载 20kb 到一个对象中吗?

它可能是没有意义的......我只需要确认它可能是 last.fm 的慢速 API。或者是吗?

您还能提供其他帮助吗?

4

5 回答 5

1

I don't think simple xml is that slow, it's slow because it is a parser but I think the 2300 curl/file_get_contents are taking a lot more time. Also why don't fetch the data and just use simplexml_load_string, do you really need to put those file on the disk of the server ?

At least loading from memory should speed up a bit things, also what kind of processing are you going on the loaded xmls ? are you sure you processing is efficient as it could be ?

于 2009-09-26T12:37:21.907 回答
1

确保从 last.fm 下载的 XML 已压缩。您可能必须包含正确的 HTTP 标头来告诉服务器您支持 gzip。它会加快下载速度,但解压缩部分会占用更多服务器资源。

还可以考虑使用异步下载来释放服务器资源。它不一定会加快这个过程,但它应该让服务器管理员高兴。

如果 XML 本身很大,请使用 SAX 解析器,而不是 DOM 解析器。

于 2009-09-26T14:59:43.873 回答
1

20kb * 2300 个用户约为 45MB。如果您以 ~25kB/sec 的速度下载,则仅下载数据就需要 30 分钟,更不用说解析它了。

于 2009-09-26T12:57:04.490 回答
0

我认为每秒有 1 个 API 调用的限制。我不确定这个政策是通过代码强制执行的,但它可能与它有关。如果您认为是这种情况,您可以通过irc.last.fm #audioscrobbler询问 IRC 上的 Last.fm 工作人员。

于 2009-09-26T15:10:15.203 回答
0

正如建议的那样,使用simplexml_load_string而不是依赖获取数据和解析simplexml_load_file- 它的运行速度大约是两倍。这是一些代码:

function simplexml_load_file2($url, $timeout = 30) {


// parse domain etc from url
$url_parts = parse_url($url);
if(!$url_parts || !array_key_exists('host', $url_parts)) return false;

$fp = fsockopen($url_parts['host'], 80, $errno, $errstr, $timeout);
if($fp) 
{
    $path = array_key_exists('path', $url_parts) ? $url_parts['path'] : '/'; 
    if(array_key_exists('query', $url_parts)) 
    {
        $path .= '?' . $url_parts['query'];
    }

    // make request
    $out = "GET $path HTTP/1.1\r\n";
    $out .= "Host: " . $url_parts['host'] . "\r\n";
    $out .= "Connection: Close\r\n\r\n";

    fwrite($fp, $out);

    // get response
    $resp = "";
    while (!feof($fp))
    {
        $resp .= fgets($fp, 128);
    }
    fclose($fp);

    $parts = explode("\r\n\r\n", $resp);
    $headers = array_shift($parts);

    $status_regex = "/HTTP\/1\.\d\s(\d+)/";
    if(preg_match($status_regex, $headers, $matches) && $matches[1] == 200)
    {
        $xml = join("\r\n\r\n", $parts);    
        return @simplexml_load_string($xml);            
    }   

}
return false; }
于 2012-04-03T08:38:57.140 回答