Как связать allow_domains с start_urls в scrapy - PullRequest
0 голосов
/ 27 апреля 2020

У меня есть широкий сканер Scrapy, который принимает CSV-файл около 20000 строк. Файл имеет имя, start_url и столбец разрешенного домена. См. Ниже:

Name               start_url               allowed_domain
place1             https://place1.co.uk    place1.co.uk
place2             https://place2.co.uk    place2.co.uk
place3             https://place3.co.uk    place3.co.uk

Ниже приведен пример кода моего сканера:

class FinalSpider(CrawlSpider): 

    name = "final"
    df = pd.read_csv("places.csv")
    start_urls = df["start_url"].values.tolist()

    custom_settings = {
        'DOWNLOAD_DELAY': 3,
        'DOWNLOADER_MIDDLEWARES': {
                'my_spider.middlewares.MySpiderDownloaderMiddleware': 543,
        },
        'SCHEDULER_PRIORITY_QUEUE': 'scrapy.pqueues.DownloaderAwarePriorityQueue',
        'CONCURRENT_REQUESTS': 100,
        'CONCURRENT_REQUESTS_PER_DOMAIN': 1,
        'RETRY_ENABLED': False,
        'AJAXCRAWL_ENABLED': True
    }

    rules = (Rule(LinkExtractor(allow_domains=(df["allowed_domain"].values.tolist())), callback='parse_item', follow=True),)


    def __init__(self):
        pass

    def parse_item(self, response):
        # do stuff

Проблема заключается в том, что моему сканеру разрешено переходить по ссылкам в любом из разрешенных доменов, не только тот, который связан с start_url.

1 Ответ

0 голосов
/ 27 апреля 2020

Вы не можете назначить allowed_domain для каждой ссылки в start_urls

Вам придется фильтровать URL-адреса внутри process_request метода DownloaderMiddleware

Вот ваш код паука

class FinalSpider(CrawlSpider): 

    name = "final"

    custom_settings = {
        'DOWNLOAD_DELAY': 3,
        'DOWNLOADER_MIDDLEWARES': {
                'my_spider.middlewares.MySpiderDownloaderMiddleware': 543,
        },
        'SCHEDULER_PRIORITY_QUEUE': 'scrapy.pqueues.DownloaderAwarePriorityQueue',
        'CONCURRENT_REQUESTS': 100,
        'CONCURRENT_REQUESTS_PER_DOMAIN': 1,
        'RETRY_ENABLED': False,
        'AJAXCRAWL_ENABLED': True
    }

    rules = (Rule(LinkExtractor(), follow=True),)

    def start_requests(self):
        df = pd.read_csv("places.csv")
        for key, row in df.iterrows():
            yield Request(url=row['start_url'],
                callback=self.parse_item,
                meta={'allowed_domain': row['allowed_domain']})

Вот код Middleware

import tldextract
from scrapy.exceptions import IgnoreRequest

class MySpiderDownloaderMiddleware(object): 

    def process_request(self, request, spider):
        site = tldextract.extract(request.url)
        site = "{}.{}".format(site.domain, site.suffix)

        if request.meta['allowed_domain'] not in site:
            raise IgnoreRequest("Filtered offsite request")
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...