You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:46:44