将一些已爬网的URL重新提供给spider / scheduler

时间:2013-05-18 14:00:22

标签: python scrapy

有一些网址(domain.com/list)列出了我需要定期抓取的10个链接。这些链接大致每30秒更改一次,因此我需要不断重新搜索domain.com/list以检查新链接。由于大小的原因,爬网所有这些链接有时需要超过30秒,因此我不能每30秒执行一次脚本,因为我最终可能会有几个并发的蜘蛛。缺少一些链接,因为蜘蛛在第一次运行期间花费的时间太长是可以接受的情况。

我写了一些蜘蛛中间件来删除已经访问过的链接(对于链接仅部分更改的情况)。我尝试在process_spider_output中包含一个新的domain.com/list请求,其中dont_filter = True,因此列表再次被提供给调度程序,但我最终得到了大量的请求。我的代码是:

def process_spider_output(self, response, result, spider):

    for i in result:
        if isinstance(i, Request):
            state = spider.state.get('crawled_links', deque([]))
            if unquote(i.url) in state or i.url in state:
                print "removed %s" % i
                continue
        yield i

    yield spider.make_requests_from_url('http://domain.com/list')

这看起来很丑陋,我不确定它是否按预期工作。我还试图挂钩蜘蛛闲置和关闭信号,试图重新抓取网站但没有成功。

重新抓取特定网址以监控经常发生的更改并且不关闭正在使用的蜘蛛的最佳方法是什么?

提前致谢

1 个答案:

答案 0 :(得分:1)

  

抓取所有这些链接有时需要超过30秒,因为   因为我,所以我不能每30秒做一次脚本   可能最终会有几个并发的蜘蛛。

通常的做法是使用包含进程PID的文件作为互斥锁,并在文件存在时退出,并且进程仍在运行。如果你将你的蜘蛛代码放入具有这种结构的程序中......

import sys
import os

PIDFILE = '/tmp/mycrawler.pid'


def do_the_thing():
    # <your spider code here>


def main():

    # Check if we're already running
    if os.path.exists(PIDFILE):
        pid = int(open(PIDFILE, 'r').read())
        try:
            os.kill(pid, 0)
            print "We're already running as PID %d" % pid
            sys.exit(1)
        except OSError:
            pass

    # Write a PID file
    open(PIDFILE, 'w').write(str(os.getpid()))

    # Now do the thing, ensuring we delete PID file when done
    try:
        do_the_thing()
    finally:
        os.unlink(PIDFILE)


if __name__ == '__main__':
    main()

...然后您可以根据需要随时从cron运行它,它将等到最后一个实例完成后再运行。