Как остановить Scrapy CrawlSpider от следующих URL-адресов, чем требуется? - PullRequest
1 голос
/ 07 октября 2019

Я хочу написать сканер со скрапом, который тянет PDF-файлы с веб-сайтов. Софар гусеничный отлично работает в отношении загрузки PDF-файлов. Тем не менее, это следует многим ссылкам, даже если я попытался сделать несколько вещей, чтобы предотвратить это.

Насколько я понимаю, я могу ограничить Crawlspider scrapy от следующих ссылок, используя правила с LinkExtractor.

Я создал собственный LinkExtractor (а также попытался создать правило напрямую без специального Linkextractor, но это дало те же результаты.)

В основном я хочу получать PDF-файлы со страницы, любую ссылку, который не заканчивается на .pdf, сканировать не следует.

Пока работает следующий код, что только файлы PDF сохраняются с помощью метода parse_docs (), однако я ожидаю, что ссылки не в формате PDF никогда не будутбыть отправленным в функцию parse_docs () вообще.

Я также пытался использовать атрибут deny в Linkextractor (идея 1) или ограничить linkextractor только одним конкретным PDF (идея 2), номногие index.php? id = ссылки продолжают сканироваться.

(извините за длинный код, но я думаю, что таким образом вы можете просто запустить файл,и не нужно перестраивать половину сканера, если его нужно сократить, пожалуйста, не стесняйтесь)

# -*- coding: utf-8 -*-
import scrapy

import re
from itertools import chain
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
EXTENSIONS = [".pdf"]

class CustomLinkExtractor(LinkExtractor):
    def __init__(self, *args, **kwargs):
        super(CustomLinkExtractor, self).__init__(*args, **kwargs)
        # Keep the default values in "deny_extensions" *except* for those types we want
        self.deny_extensions = [ext for ext in self.deny_extensions if ext not in EXTENSIONS]
        self.allow = (r'.*\.pdf',) 
        #self.deny = ('index\.php',) #idea 1

class BremenSpider(CrawlSpider):
    name = 'bremen'
    allowed_domains = ['www.bremische-buergerschaft.de',"bremische-buergerschaft.de"]
    start_urls = ['https://www.bremische-buergerschaft.de/index.php?id=570']

    def __init__(self, *args, **kwargs):
        self.rules = (
            Rule(CustomLinkExtractor(), callback="parse_docs"),
            #idea 2
            #Rule(LinkExtractor(allow = ('/dokumente/wp19/land/protokoll/P19L0076.pdf')), callback="parse_docs"),
            )
        super(BremenSpider, self).__init__(*args, **kwargs)


    def parse_docs(self, response):
        if hasattr(response, "text"):
            # The response is text - we assume html. Normally we'd do something
            # with this, but this demo is just about pdf content, so...
            self.logger.info("not parsing url: %s", response.url)
            pass
        else:
            extension = list(filter(lambda x: response.url.lower().endswith(x), EXTENSIONS))[0]
            if extension:
                # This is a pdf 
                path = response.url.split('/')[-1]                
                self.logger.info('Saving PDF %s', path)
                with open(path, 'wb') as f:
                    f.write(response.body) 

Я бы ожидал, что будет сканироваться только start_url с index.php? id = 570 и .pdf,но когда я запускаю сканер на CLI, он также сканирует множество других ссылок index.php? ....

Я неправильно понимаю вывод CLI или мой LinkExtractor неверен?

1 Ответ

0 голосов
/ 07 октября 2019

pdf (без точки) включено в scrapy.linkextractors.IGNORED_EXTENSIONS, поэтому по умолчанию оно игнорируется. Я думаю, что следующее должно решить вашу проблему:

from scrapy.linkextractors import IGNORED_EXTENSIONS
CUSTOM_IGNORED_EXTENSIONS = IGNORED_EXTENSIONS.copy()
CUSTOM_IGNORED_EXTENSIONS.remove('pdf')

тогда, в атрибуте rules паука вы можете определить правило с помощью следующего экстрактора ссылок: LinkExtractor(allow=r'.*\.pdf', deny_extensions=CUSTOM_IGNORED_EXTENSIONS)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...