Итак, Армин, вот код
Spider Script
import scrapy
from scrapy.loader import ItemLoader
from ..items import NorisbankItem
class TestSpider(scrapy.Spider):
name = "nbtest"
allowed_domains = ['norisbank.de']
start_urls = ['https://www.norisbank.de']
custom_settings={ 'FEED_URI': "norisbank_%(time)s.csv",
'FEED_FORMAT': 'csv',
}
def parse(self, response):
page = response.url.split("/")[-2]
filename = 'nbtest-%s.html' % page
with open(filename, 'wb') as f:
f.write(response.body)
self.log('Saved file %s' % filename)
#Content Extraction
print(response.url)
l = ItemLoader(NorisbankItem(), response=response)
l.add_xpath('sitename', "//meta[@property='og:site_name']/@content")
l.add_xpath('siteurl', "//link[@rel='canonical']/@href")
l.add_xpath('dbCategory',"//meta[@name='dbCategory']/@content")
l.add_css('title','title::text')
l.add_xpath('descriptions',"//meta[@name='description']/@content")
l.add_xpath('date',"//meta[@name='date']/@content")
l.add_xpath('version',"//meta[@name='v']/@content")
l.add_xpath('time',"//meta[@name='time']/@content")
l.add_xpath('sitecontent','//body//p//text()')
yield l.load_item()
all_pages = response.xpath('//a[contains(@href, "html")]/@href').getall()
for next_page in all_pages:
next_page = response.urljoin(next_page)
yield scrapy.Request(next_page, callback=self.parse)
Я удалил код, связанный с элементами. Все, что связано с изменением данных, я всегда использую загрузчики элементов. Вы видите, что нам нужно импортировать ItemLoader и Item Class в паук. Мы создаем экземпляр класса загрузчика элементов, мы должны определить класс элемента для его заполнения и убедиться, что загрузчик элементов может использовать ответ, чтобы мы могли выбрать XPATH для этого ответа.
Затем мы используем метод add_xpath (), первый Аргумент определяет поле элемента в items.py, а второй аргумент - это xpath. Обратите внимание, что нам не нужно выполнять get (). Если к этому xpath привязано несколько значений, загрузчики элементов поместят их в список. Фактически, это именно то, что делает Itemloaders: он помещает данные в список независимо от того, одно значение это или больше. Этот список затем заполняет словарь элементов. Мы должны предоставить метод load_item для заполнения этого словаря элементов в конце. Не слишком разные, но более компактные и лаконичные.
Items
import scrapy
from scrapy.item import Item,Field
from scrapy.loader.processors import MapCompose,Join
def clean(x):
if x:
return x
class NorisbankItem(Item):
define the fields for your item here like:
name = scrapy.Field()
sitename = scrapy.Field()
siteurl = scrapy.Field()
dbCategory = scrapy.Field()
title = scrapy.Field()
descriptions = scrapy.Field()
date = scrapy.Field()
version = scrapy.Field()
time= scrapy.Field()
sitecontent = scrapy.Field(input_processor=MapCompose(str.strip,clean),
output_processor=Join(' '))
Здесь, в items.py, мы определяем поля элементов. Контент сайта - это то место, где мы применяем процессоры ввода и вывода, которые дают возможность загрузчикам элементов. Есть несколько способов использовать процессор ввода / вывода, самый простой я нахожу в коде. Процессоры ввода используются для изменения данных до того, как данные будут заполнены в словаре элементов. Здесь мы используем MapCompose, он принимает все значения и передает их в функцию / метод, который мы указываем, здесь мы используем метод удаления строки, мы удаляем строку и затем передаем каждое значение в функцию очистки.
Это Чистая функция - наша собственная, опять же другая мощь Itemloaders. Просто мы хотим вернуть значения, если они не пустые, т.е. не ''. Помните, что это будет помещено в список значений, что и делает Itemloader при заполнении словаря элементов. Здесь, в аутпроцессоре, мы берем каждое значение в списке и объединяем его, разделяя его пробелом.
Другие мысли
Старайтесь не путать селекторы CSS и селекторы XPATH при использовании itemloaders или любой скрипт scrapy. Я предпочитаю селекторы xpath, так как у вас больше гибкости. Если вы не хотите использовать загрузчики элементов или скрипт не вызывает их, используйте get () и getall () вместо extract (), это просто быстрее и немного короче.