Python 在Django中同时运行多个web爬虫

Python 在Django中同时运行多个web爬虫,python,django,asynchronous,web-crawler,python-multithreading,Python,Django,Asynchronous,Web Crawler,Python Multithreading,我为Django创建了一个名为crawl.py的自定义管理命令 我想让它同时运行两个爬虫。 我的爬虫程序都是一个对象,具有一个crawl()函数,该函数运行一个无限循环并与orm交互 def crawl(self): current_page = self.start_page while True: page_response = requests.get('http://magdeleine.co/browse/page/{}/'.format(current

我为Django创建了一个名为crawl.py的自定义管理命令

我想让它同时运行两个爬虫。 我的爬虫程序都是一个对象,具有一个crawl()函数,该函数运行一个无限循环并与orm交互

def crawl(self):
    current_page = self.start_page
    while True:
        page_response = requests.get('http://magdeleine.co/browse/page/{}/'.format(current_page))
        page_soup = BeautifulSoup(page_response.text)
        image_links = [link["href"] for link in page_soup.find_all('a', {'class': 'photo-link'})]


        for image_link in image_links:
            response = requests.get(image_link)
            image_page_soup = BeautifulSoup(response.text)
            print('getting image source link')
            image_source_link = image_page_soup.find('a',{'class': 'download'})['href']

            #Get Tags
            print('getting tags')
            ul = image_page_soup.find('ul', {'class': 'tags'})
            tag_links = ul.find_all('a', {'rel':'tag'})
            tag_names = [tag_link.string for tag_link in tag_links]
            try:
                tag_names.remove('editor\'s pick')
            except:
                pass

            if not Image.objects.filter(url=image_source_link).exists():
                image = Image(url=image_source_link, origin="MG")
                print('creating thumbnail')
                image.create_thumb()
                image.save()
                # get or create a new tag for every element in the list
                for tag_name in tag_names:
                    tag, created = Tag.objects.get_or_create(name=tag_name)
                    image.tags.add(tag)

        current_page+=1
        print("end page")
在我的管理指挥部

class Command(BaseCommand):

    def handle(self, *args, **options):
        pexel_crawler = PexelCrawler()
        pexel_crawler.crawl()

        magdeleine_crawler = MagdeleineCrawler()
        magdeleine_crawler.crawl()
我想同时运行这两个.crawl()命令。
另外,如果有人能详细说明这是如何在生产与开发中实现的,以及针对这一点的最佳解决方案。

您应该能够使用gevent实现这一点,例如:

import gevent
from django.core.management.base import BaseCommand

class Command(BaseCommand):

    def handle(self, *args, **options):
        pexel_crawler = PexelCrawler()
        magdeleine_crawler = MagdeleineCrawler()
        pexel_job = gevent.spawn(pexel_crawler.crawl)
        magdeleine_job = gevent.spawn(magdeleine_crawler.crawl)
        gevent.joinall([pexel_job, magdeleine_job])
我相信这会起作用,只要两个爬虫都在运行,管理命令就会在前台运行。不过我会小心,因为如果这能如预期的那样工作,它将真正成为一个无限循环,永远不会停止。

我建议您使用它来完成该任务。 爬网操作可能需要很多时间,如果我们从cmd调用它,我们可以控制任务,但在生产环境中,您将从cron/view/etc调用它,因此更好地控制它 任务生命周期

安装芹菜和Django管理工具

对于MessageBroker,我建议安装RabbitMQ

apt-get install rabbitmq-server
在Django项目的settings.py中添加

import djcelery

djcelery.setup_loader()

CELERYBEAT_SCHEDULER = 'djcelery.schedulers.DatabaseScheduler' #To make crawl call by shedule.
在项目中创建文件tasks.py,并将此代码放入其中

from __future__ import absolute_import
from celery import shared_task
from django.core.management import call_command
@shared_task
def run_task():
    print call_command('your_management_command', verbosity=3, interactive=False)
要控制您的任务,请安装

首先运行您的任务:

运行rabbitmq服务器

service rabbitmq-server start  
然后去吃芹菜

service celeryd start
然后控制任务的执行

service flower start

就是这样,您现在可以运行爬虫程序任务,您可能会遇到任何问题。

所以我需要将每个爬虫程序分离为不同的管理命令来一起运行?使用分离的管理命令,您可以控制执行并在作业占用大量内存/cpu/等时停止。如果它们没有响应,您可以重新启动作业。好的,然后呢如果两个任务同时尝试添加到数据库中,会发生这种情况吗?不管是否同时添加,这都无关紧要。在大多数情况下,所有插入操作都添加到队列中。所以图像将保存在数据库中。不要担心秩序。您甚至可以让分布式爬虫在多个节点中运行任务,并将所有任务存储在单个数据库中。
service celeryd start
service flower start