如何将Django中的URL变量传递给Scrapy并动态配置爬虫?
Django + Scrapy集成:动态传递URL并启动爬虫
我来帮你搞定这个动态配置爬虫的问题,核心就是让Scrapy爬虫能接收Django传过来的参数,动态设置allowed_domains和start_urls,同时确保Django端能正确触发爬虫调度。
第一步:修改Scrapy爬虫,支持动态参数
你的icrawler.py现在是固定的域名和起始URL,我们要让它能从外部接收参数。对于CrawlSpider,重写__init__方法就能实现:
from scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LinkExtractor class IcrawlerSpider(CrawlSpider): name = 'icrawler' # 先留空,后续通过参数动态赋值 allowed_domains = [] def __init__(self, url=None, domain=None, *args, **kwargs): super().__init__(*args, **kwargs) # 从scrapyd传递的参数中获取URL和域名 self.start_urls = [url] if url else [] # allowed_domains不需要带http/https,你Django端用urlparse获取的netloc刚好是正确格式 self.allowed_domains = [domain] if domain else [] rules = ( Rule(LinkExtractor(allow=r'Items/'), callback='parse_item', follow=True), ) def parse_item(self, response): i = {} # 这里可以根据你的需求提取数据,比如示例: # i['page_title'] = response.css('title::text').get() # i['page_url'] = response.url return i
第二步:修正Django端的调度代码
你当前的Django代码有个小问题:调度爬虫时传递的url=url是笔误,应该用从序列化器获取的site.url。另外确保domain参数传递正确(你用urlparse(site.url).netloc处理的是对的)。
调整后的调度代码片段:
def post(self, request, format=None): data = request.data serializer = self.serializer_class(data=data) if serializer.is_valid(): site = serializer.create(data) domain = urlparse(site.url).netloc site_id = site.id # 这里假设unique_id是你生成的唯一标识,比如用site_id或者uuid都可以 unique_id = str(site_id) # 或者用uuid.uuid4().hex生成随机值 settings = { 'unique_id': unique_id, 'USER_AGENT': 'Mozilla/5.0 (compatible; Googlebot/2.1; +http://www.google.com/bot.html)' } # 关键:把url和domain参数传递给爬虫 task_id = scrapyd.schedule( 'default', 'icrawler', settings=settings, url=site.url, domain=domain ) task = { 'task_id': task_id, 'unique_id': unique_id, 'status': 'started' } resp = { 'task': task, 'data': serializer.data, 'status': status.HTTP_201_CREATED } return Response(resp) else: return Response(serializer.errors, status=status.HTTP_400_BAD_REQUEST)
关键逻辑说明
- Scrapy爬虫的
__init__方法会接收scrapyd调度时传递的url和domain参数,动态设置start_urls和allowed_domains,这样每次调用爬虫都能针对不同的目标网站。 - 你用
urlparse(site.url).netloc获取的域名刚好符合Scrapyallowed_domains的要求(不需要带http/https前缀),直接传递就行。 - 要确保scrapyd服务已经正常启动(默认地址是
http://localhost:6800),如果scrapyd在远程服务器,需要修改配置允许外部访问,同时Django项目能访问到这个地址。
内容的提问来源于stack exchange,提问作者chimezie daluchi
相关产品推荐
相关产品推荐

