Python 在Django中同时运行多个web爬虫
我为Django创建了一个名为crawl.py的自定义管理命令 我想让它同时运行两个爬虫。 我的爬虫程序都是一个对象,具有一个crawl()函数,该函数运行一个无限循环并与orm交互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
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