在Django中同时运行多个Web爬虫

时间:2015-09-30 16:23:26

标签: 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_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()命令。 此外,如果有人能详细说明如何在生产与开发中实现这一点,并为此制定最佳解决方案。

2 个答案:

答案 0 :(得分:1)

您应该可以使用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])

我相信这样做会有效,并且只要两个爬虫都在运行,就会让管理命令在前台运行。我会小心,因为如果这个按预期工作,它将真正是一个无限循环,永远不会停止。

答案 1 :(得分:1)

我建议您使用Celery执行该任务。 抓取操作可能需要很长时间,如果我们从cmd调用它,我们可以控制任务但是在生产中你会从cron / view / etc调用它以便更好地控制它 任务生命周期。

安装Celery和Django管理工具djcelery

pip install celery
pip install djcelery

对于消息代理,我建议安装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)

控制您的任务安装flower

apt-get install flower

首先运行您的任务:

运行rabbitmq服务器

service rabbitmq-server start  

然后运行芹菜

service celeryd start

然后开花来控制你的任务的执行。

service flower start

现在你可以运行你的爬虫任务了,你会遇到任何麻烦。