Есть ли способ получить текст внутри тега привязки в Crawlspider Scrapy? - PullRequest
1 голос
/ 01 апреля 2019

У меня есть сканер сканирования, который сканирует данный сайт до определенного отдела и загружает файлы PDF на этом сайте. Все работает нормально, но вместе со ссылкой в ​​формате PDF мне также нужен текст внутри тега привязки.

например:

<a href='../some/pdf/url/pdfname.pdf'>Project Report</a>

рассмотрите этот якорный тег, в обратном вызове я получаю объект ответа, и наряду с этим объектом мне нужен текст внутри этого тега, например, «Отчет по проекту». Есть ли способ получить эту информацию вместе с объектом ответа. Я прошел через https://docs.scrapy.org/en/latest/topics/selectors.html ссылку, но это не то, что я ищу.

пример кода:

class DocumunetPipeline(scrapy.Item):
    document_url = scrapy.Field()
    name = scrapy.Field()  # name of pdf/doc file
    depth = scrapy.Field()

class MySpider(CrawlSpider):
    name = 'pdf'
    start_urls = ['http://www.someurl.com']
    allowed_domains = ['someurl.com']
    rules = (
        Rule(LinkExtractor(tags="a", deny_extensions=[]),
             callback='parse_document', follow=True),
    )


    def parse_document(self, response):
        content_type = (response.headers
                        .get('Content-Type', None)
                        .decode("utf-8"))
        url = response.url
        if content_type == "application/pdf":
            name = response.headers.get('Content-Disposition', None)
            document = DocumunetPipeline()
            document['document_url'] = url
            document['name'] = name
            document['depth'] = response.meta.get('depth', None)
            yield document

Ответы [ 2 ]

2 голосов
/ 01 апреля 2019

Кажется, что это не задокументировано, но атрибут meta содержит текст ссылки. Обновляется в этой строке . Минимальный пример:

from scrapy.spiders import Rule, CrawlSpider
from scrapy.linkextractors import LinkExtractor


class LinkTextSpider(CrawlSpider):
    name = 'linktext'
    start_urls = ['https://example.org']
    rules = [
        Rule(LinkExtractor(), callback='parse_document'),
    ]

    def parse_document(self, response):
        return dict(
            url=response.url,
            link_text=response.meta['link_text'],
        )

, который производит вывод, подобный:

2019-04-01 12:03:30 [scrapy.core.engine] INFO: Spider opened
2019-04-01 12:03:30 [scrapy.extensions.logstats] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2019-04-01 12:03:30 [scrapy.extensions.telnet] INFO: Telnet console listening on 127.0.0.1:6023
2019-04-01 12:03:31 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://example.org> (referer: None)
2019-04-01 12:03:32 [scrapy.downloadermiddlewares.redirect] DEBUG: Redirecting (302) to <GET https://www.iana.org/domains/reserved> from <GET http://www.iana.org/domains/example>
2019-04-01 12:03:33 [scrapy.core.engine] DEBUG: Crawled (200) <GET https://www.iana.org/domains/reserved> (referer: None)
2019-04-01 12:03:33 [scrapy.core.scraper] DEBUG: Scraped from <200 https://www.iana.org/domains/reserved>
{'url': 'https://www.iana.org/domains/reserved', 'link_text': 'More information...'}
2019-04-01 12:03:33 [scrapy.core.engine] INFO: Closing spider (finished)
0 голосов
/ 01 апреля 2019

Я считаю, что лучший способ добиться этого - не использовать правила сканирования, а вместо этого использовать регулярное сканирование с помощью собственных parse_* методов для обработки всех ответов.

Затем, когда вы выдаете запрос с parse_document в качестве обратного вызова, вы можете включить текст ссылки в параметр meta вашего запроса и прочитать его из response.meta в вашем методе parse_document.

class MySpider(CrawlSpider):
    name = 'pdf'
    start_urls = ['http://www.someurl.com']
    allowed_domains = ['someurl.com']

    def parse(self, response):
        for link in response.css('a'):
            yield response.follow(
                link,
                callback=self.parse_document,
                meta={'link_text': link.xpath('text()').get()}
            )


    def parse_document(self, response):
        # …
        if content_type == "application/pdf":
            # …
            document = DocumunetPipeline()
            # …
            document['link_text'] = response.meta['link_text']
            yield document
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...