1

我有一个个人网站,可以从我最喜欢的音乐博客中抓取和收集 MP3 以供以后收听...

它的工作方式是 CRON 作业每分钟运行一次 .php 脚本,以抓取数据库中的下一个博客。结果被放入数据库,然后第二个 .php 脚本抓取收集到的链接。

脚本只爬入页面的两个级别,因此.. 主页 www.url.com 和该页面上的链接 www.url.com/post1 www.url.com/post2

我的问题是,当我开始收集更多的博客时。它们每 20 到 30 分钟才被扫描一次,当我将新博客添加到脚本中时,会在扫描链接时进行备份,因为每分钟只处理一个链接。

由于 PHP 的工作方式,由于脚本执行时间的原因,我似乎不能只允许脚本处理多个或有限数量的链接。内存限制。超时等

此外,我不能运行同一脚本的多个实例,因为它们会在数据库中相互覆盖。

我可以加快这个过程的最佳方法是什么。

有没有一种方法可以让多个脚本影响数据库但写入它们以便它们不会相互覆盖但将结果排队?

有没有办法在 PHP 中创建线程,以便脚本可以按照自己的节奏处理链接?

有任何想法吗?

谢谢。

4

5 回答 5

2

使用卷曲多!

Curl-mutli 将让您并行处理页面。

http://us3.php.net/curl

大多数时候,您在网站上等待,进行 db 插入和 html 解析的速度要快几个数量级。

您创建一个要抓取的博客列表,将它们发送到 curl multi。等待然后串行处理所有调用的结果。然后,您可以在下一层进行第二次传递

http://www.developertutorials.com/blog/php/parallel-web-scraping-in-php-curl-multi-functions-375/

于 2009-06-08T19:17:36.913 回答
2

pseudo code for running parallel scanners:

start_a_scan(){
    //Start mysql transaction (needs InnoDB afaik)        
    BEGIN 
        //Get first entry that has timed out and is not being scanned by someone
        //(And acquire an exclusive lock on affected rows)
        $row = SELECT * FROM scan_targets WHERE being_scanned = false AND \
                (scanned_at + 60) < (NOW()+0) ORDER BY scanned_at ASC \
                      LIMIT 1 FOR UPDATE
        //let everyone know we're scanning this one, so they'll keep out
        UPDATE scan_targets SET being_scanned = true WHERE id = $row['id']
    //Commit transaction
    COMMIT
    //scan
    scan_target($row['url'])
    //update entry state to allow it to be scanned in the future again
    UPDATE scan_targets SET being_scanned = false, \
              scanned_at = NOW() WHERE id = $row['id']
}

You'd probably need a 'cleaner' that checks periodically if there's any aborted scans hanging around too, and reset their state so they can be scanned again.

And then you can have several scan processes running in parallel! Yey!

cheers!

EDIT: I forgot that you need to make the first SELECT with FOR UPDATE. Read more here

于 2009-06-08T18:43:04.877 回答
1

由于 PHP 的工作方式,由于脚本执行时间的原因,我似乎不能只允许脚本处理多个或有限数量的链接。内存限制。超时等

如果您的代码泄漏内存,内存限制只是一个问题。您应该解决这个问题,而不是提高内存限制。脚本执行时间是一种安全措施,您可以简单地为您的 cli 脚本禁用它。

此外,我不能运行同一脚本的多个实例,因为它们会在数据库中相互覆盖。

您可以以实例不会相互覆盖的方式构建您的应用程序。一种典型的方法是按站点进行分区;例如。为您要抓取的每个站点启动一个单独的脚本。

于 2009-06-08T18:20:06.883 回答
1

这肯定不是您问题的答案,但如果您愿意学习 python,我建议您查看Scrapy,这是一个可以满足您需求的开源网络爬虫/爬虫框架。同样,它不是 PHP,而是 Python。它是多么可分配等等......我自己使用它。

于 2009-06-08T17:52:15.023 回答
0

CLI 脚本不受最大执行时间的限制。内存限制通常不是问题,除非您在内存中随时都有大量数据。超时应该由您的应用程序优雅地处理。

应该可以更改您的代码,以便您可以一次运行多个实例 - 您必须发布脚本以供任何人进一步建议。正如彼得所说,您可能需要查看设计。在 pastebin 中提供代码将帮助我们帮助您:)

于 2009-06-08T17:09:33.430 回答