【问题标题】:Is it possible to speed up phpQuery?是否可以加快 phpQuery?
【发布时间】:2011-11-10 18:23:30
【问题描述】:

我正在尝试读取一个 12MB 以上的文件,该文件有一个大的 HTML 表格,如下所示:

<table>
    <tr>
        <td>a</td>
        <td>b</td>
        <td>c</td>
        <td>d</td>
        <td>e</td>
    </tr>
    <tr>
        <td>a</td>
        <td>b</td>
        <td>c</td>
        <td>d</td>
        <td>e</td>
    </tr>
    <tr>..... up to 20,000+ rows....</tr>
</table>

现在我是这样刮的:

<?

require_once 'phpQuery-onefile.php';

$d = phpQuery::newDocumentFile('http://localhost/test.html');

$last_index = 20000;

for ($i = 1; $i <= $last_index; $i++)
{
    $set['c1']  = $d['tr:eq('.$i.') td:eq(0)']->text();
    $set['c2']  = $d['tr:eq('.$i.') td:eq(1)']->text();
    $set['c3']  = $d['tr:eq('.$i.') td:eq(2)']->text();
    $set['c4']  = $d['tr:eq('.$i.') td:eq(3)']->text();
    $set['c5']  = $d['tr:eq('.$i.') td:eq(4)']->text();
}

// code to insert to db here... 

?>

我的基准测试表明大约需要 5.25 小时才能将 1,000 行数据抓取并插入到数据库中。鉴于这些数据,完成全部 20,000 多行大约需要 5 天时间。

我的本​​地机器正在运行:

  • XAMPP
  • 赢 7
  • 处理器,i3 2100 3.1GHz
  • 内存,G.Skill RipJaws X 4GB 双
  • 硬盘,旧 SATA

有什么方法可以加快这个过程吗?也许我刮错了?请注意,该文件可在本地访问,因此我使用了http://localhost/test.html

稍微快一点的解决方案:

for ($i = 1; $i <= $last_index; $i++)
{
    $r = $d['tr:eq('.$i.')'];

    $set['c1']  = $r['td:eq(0)']->text();
    $set['c2']  = $r['td:eq(1)']->text();
    $set['c3']  = $r['td:eq(2)']->text();
    $set['c4']  = $r['td:eq(3)']->text();
    $set['c5']  = $r['td:eq(4)']->text();
}

// code to insert to db here... 

?>

【问题讨论】:

  • 您应该使用现成的表格提取库,而不是自己收集数据。 (例如blog.mspace.fm/2009/10/14/parse-an-html-table-with-php - 尽管您必须注意该正则表达式对于您的情况是否足够健壮。)
  • @mario phpQuery 不是已经是现成的库了吗?

标签: php performance phpquery


【解决方案1】:

我从未使用过 phpQuery,但这看起来是一种非常 次优化的解析大型文档的方法:phpQuery 可能每次加载时都必须遍历整个内容一行使用tr:eq('.$i.')

更直接(也可能更快)的方法是简单地遍历文档的每个tr 元素,并在foreach 循环中处理每个元素的子元素。你甚至不需要 phpQuery。

请参阅How to Parse XML File in PHP 了解各种解决方案。

【讨论】:

  • @IMB 如果 HTML 是干净的,那没关系。但是,您可以先尝试使用 phpQuery,您只需要更改方法:让 phpQuery 一次性加载所有 trs(即所有名为 tr... 的 tables 孩子),然后步行通过他们。这可能已经快了几个数量级
  • HTML 不是很干净。我有点明白你在说什么,但除了我上面所做的之外,我不知道如何在代码中做到这一点。如何在不遍历每个 TR 的情况下加载所有 TR?我必须做一个双 foreach,才能让每个 TD 都正确?不过对我来说听起来更慢。
  • @IMB 相信我,它可能会更快。您现在的做法是,它可能必须在每次迭代时解析整个文档。我不知道 phpQuery 是如何实现的,但这几乎可以肯定是最次优的方法。
  • 你说得对,谢谢。我重新考虑了你所说的,我只需要一个 foreach。我编辑了上面的代码,现在速度快了 20%。虽然我认为它可以更快 LOL,你怎么看?
  • @IMB 嗯,这仍然不是我的意思。我的意思是一次加载所有的孩子。等一下,我去找个例子
猜你喜欢
  • 2013-04-17
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多