Я использую Scrapy для сканирования и очистки данных с веб-сайтов, которые в основном состоят из html-страниц и файлов PDF (я изменил IGNORED_EXTENSIONS
, чтобы разрешить очистку pdf-файлов).Извлечение информации из элементов привязки, приводящих к файлам PDF
Мне нужно извлечь текст, который захватывается между <a>
тегами:
<a href='some_document.pdf'>I need this text</a>
Очевидно, что я не могу сделать response.text или response.css, так как есть только байты для чтения (вы получаете AttributeError).
Одна вещь, которая пришла мне на ум, заключалась в обходе страницы, извлечении всех ссылок с этой страницы и сохранении их в текстовом файле. Это сработало, за исключением того, что у меня появилось много дублирующих ссылок, ссылок, которые были сломаны (думаю, 403, 404, 500) или много ссылок, на которые меня не волновало. Я думаю, что должен быть лучший способ!
При чтении документации по Scrapy я наткнулся на документ для LxmlLinkExtractor. Там в «Конструктор», он имеет 2 интересные поля:
- метки (ул или список) - тег или список тегов, которые следует учитывать при извлечении ссылки. По умолчанию ('a', 'area').
- attrs (list) - атрибут или список атрибутов, которые следует учитывать при поиске ссылок для извлечения (только для тех тегов, которые указаны в параметре тегов). По умолчанию («HREF»,)
И это заставило меня задуматься, возможно ли, чтобы захватить значения атрибутов <a>
элемента перед сканированием его. Я прав? И если да, как я могу захватить текст между тегами?
Исходный код:
class ArchiveSpider(CrawlSpider):
...some code...
rules = [
Rule(LinkExtractor(allow=[re.compile('pdf', re.IGNORECASE)]),
callback='parse_pdf',
follow=True),
Rule(LinkExtractor(), callback='parse_item', follow=True)
]
def parse_pdf(self, response):
yield dict(url=response.url)
def parse_item(self, response):
if re.search(re.compile('pdf', re.IGNORECASE, response.headers.get('Content-Type').decode('utf-8')):
parse_pdf(self, response)
title = response.css('title::text').extract()[0].strip() if response.css('title::text') else ''
yield dict(title=title, url=response.url)