Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/273.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
爬行、刮削和穿线?使用php_Php_Multithreading_Screen Scraping_Web Crawler - Fatal编程技术网

爬行、刮削和穿线?使用php

爬行、刮削和穿线?使用php,php,multithreading,screen-scraping,web-crawler,Php,Multithreading,Screen Scraping,Web Crawler,我有一个个人网站,从我最喜欢的音乐博客中收集MP3供以后收听 它的工作方式是CRON作业每分钟运行一次.php脚本,在数据库中抓取下一个博客。结果被放入数据库,然后第二个.php脚本对收集的链接进行爬网 脚本只在页面中向下爬行两级,因此。。主页www.url.com及其上的链接www.url.com/post1 www.url.com/post2 我的问题是,随着我开始收集更多的博客。它们每20到30分钟只扫描一次,当我在脚本中添加一个新博客时,扫描链接时会有一个备份,因为每分钟只处理一个链接

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

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

脚本只在页面中向下爬行两级,因此。。主页www.url.com及其上的链接www.url.com/post1 www.url.com/post2

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

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

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

我能加快这一进程的最佳方式是什么

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

是否有某种方法可以在PHP中创建线程,以便脚本能够以自己的速度处理链接

有什么想法吗


谢谢。

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


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

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


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

这肯定不是您问题的答案,但如果您愿意学习python,我建议您看看哪些应该满足您的需要。同样,这不是PHP,而是Python。它是如何非常可分配的等等。。。我自己使用它。

这肯定不是你问题的答案,但如果你愿意学习python,我建议你看看哪些应该满足你的需要。同样,这不是PHP,而是Python。它是如何非常可分配的等等。。。我自己用

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

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

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

您可以以实例不相互重写的方式构造应用程序。一个典型的方法是对每个站点进行分区;为每个要爬网的站点启动一个单独的脚本

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

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

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


您可以以实例不相互重写的方式构造应用程序。一个典型的方法是对每个站点进行分区;例如,为要爬网的每个站点启动单独的脚本。

运行并行扫描程序的伪代码:

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']
}
开始扫描(){
//启动mysql事务(需要InnoDB afaik)
开始
//获取第一个已超时且未被他人扫描的条目
//(并获取受影响行的独占锁)
$row=从正在扫描的扫描目标中选择*\
(在+60处扫描)<(现在()+0)ASC处扫描的订单\
更新限制为1
//让每个人都知道我们正在扫描这张照片,这样他们就不会进来了
更新正在扫描的扫描目标集=true,其中id=$row['id']
//提交事务
犯罪
//扫描
扫描目标($row['url']))
//更新条目状态以允许将来再次扫描
更新正在扫描的扫描目标集=错误\
已扫描\u at=NOW()其中id=$row['id']
}
您可能需要一个“清洁器”,定期检查是否有任何中止的扫描挂起,并重置其状态,以便再次扫描

然后你可以有几个扫描进程并行运行!是的

干杯


编辑:我忘了您需要使用进行第一次选择以进行更新。阅读更多运行并行扫描仪的伪代码:

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']
}
开始扫描(){
//启动mysql事务(需要InnoDB afaik)
开始
//获取第一个已超时且未被他人扫描的条目
//(并获取受影响行的独占锁)
$row=从正在扫描的扫描目标中选择*\
(在+60处扫描)<(现在()+0)按扫描顺序订购