Простой сканер Scrapy не будет использовать конвейер - PullRequest
0 голосов
/ 03 апреля 2020

Справочная информация

Я пытаюсь научиться Scrapy на примере.

На данный момент я сделал CrawlSpider в состоянии перейти на страницу, следите за всеми ссылки, извлечение данных с помощью CSS селекторов и заполнение элементов с помощью загрузчика элементов.

Я сейчас пытаюсь добавить произвольный конвейер, просто чтобы я мог заставить его работать.

Моя проблема в том, что конвейеры элементов для CrawlSpiders, кажется, нуждаются в дополнительных определениях, чем те, которые используют scrapy.Spider - я не могу найти рабочие примеры конвейеров CrawlSpider.

Какой мой код на самом деле делает

Начинается на странице Википедии для lexus и следует за всеми другими страницами Википедии, которые ссылаются на него. Затем он извлекает заголовок каждой страницы и заголовки из первой таблицы. Они хранятся в элементах, которые затем печатаются в текстовом документе.

lexuswikicrawl.py

import scrapy
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.loader import ItemLoader
from wikicars.items import WikiItem

#Global variables
pages = {}
failed_pages = 1
filename = 'wiki.txt'



class GenSpiderCrawl(CrawlSpider):
    name = 'lexuswikicrawl'

    #Start at the lexus wikipedia page, and only follow the wikipedia links
    allowed_domains = ['wikipedia.org']
    start_urls = ['https://en.wikipedia.org/wiki/Lexus']

    #There are no specific rules specified below, therefore all links will be followed              
    rules = (Rule(LinkExtractor(), callback = 'parse_page'),)

    #Define what selectors to crawl
    def parse_page(self, response): 
        global pages
        global failed_pages

        #Try and capture the page title using CSS selector
        #If not, keep count of the amount of failed selectors
        try:
            pagename = (response.css('div#content.mw-body > h1#firstHeading::text').extract())[0]
        except:
            pagename = ('Failed pagename: '+ str(failed_pages))
            failed_pages += 1


        # Capture table categories that fall under the CSS selector for regular text items
        tabcat = response.css('#mw-content-text > div > table.infobox.vcard > tbody > tr > th::text').extract() 
        # Capture tale categories that fall under CSS selector for text with hyperlinks
        for i in range(20):
            tabcatlink1 = response.css('#mw-content-text > div > table.infobox.vcard > tbody > tr:nth-child('+str(i)+') > th > a::text').extract()
            tabcatlink2 = response.css('#mw-content-text > div > table.infobox.vcard > tbody > tr:nth-child('+str(i)+') > th > div > a::text').extract()
            if len(tabcatlink1) > 0:
                tabcat.append(tabcatlink1)
            else:
                pass
            if len(tabcatlink2) > 0:
                tabcat.append(tabcatlink2)
            else: 
                continue

        #Load 'pagename' and 'categories' into a new item

        page_loader = ItemLoader(item=WikiItem(), selector = tabcat)

        page_loader.add_value('title', pagename)
        page_loader.add_value('categories', tabcat)

        #Store the items in an overarching dictionary structure
        pages[pagename] = page_loader.load_item()

        #Try and print the results to a text document
        try:
            with open(filename, 'a+') as f:
                f.write('Page Name:'   + str(pages[pagename]['title'])+ '\n')
        except: 
            with open(filename, 'a+') as f:
                f.write('Page name error'+ '\n')
        try:
            with open(filename, 'a+') as f:
                f.write('Categories:'  + str(pages[pagename]['categories'])+ '\n')
        except:
            with open(filename, 'a+') as f:
                f.write('Table Category data not available'  + '\n')

items.py

import scrapy
from scrapy.loader.processors import TakeFirst, MapCompose

def convert_categories(categories):
    categories = (str(categories).upper().strip('[]'))
    return categories

def convert_title(title):
    title = title.upper()
    return title

class WikiItem(scrapy.Item):

    categories = scrapy.Field(
                              input_processor = MapCompose(convert_categories)
                              )

    title      = scrapy.Field(
                              input_processor = MapCompose(convert_title)

pipelines.py

Здесь я подозреваю, что возникла проблема. В настоящее время я думаю, что мне нужно нечто большее, чем просто process_item () для запуска моего конвейера. Я перепробовал все, что мог, чтобы изменить примеры: https://docs.scrapy.org/en/latest/topics/item-pipeline.html.

from scrapy.exceptions import DropItem

class PipelineCheck(object):

    def process_item(self, item, spider):
        print('I am a pipeline this is an item:' + str(item) + '\n')

settings.py

Я объявил свой трубопровод и его приоритет. Я также объявил универсальный пользовательский агент c. Нужно ли установить дополнительную переменную?

BOT_NAME = 'wikicars'

SPIDER_MODULES = ['wikicars.spiders']
NEWSPIDER_MODULE = 'wikicars.spiders'

USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/74.0.3729.169 Safari/537.36'

ROBOTSTXT_OBEY = True

ITEM_PIPELINES = {
    'wikicars.pipelines.PipelineCheck': 100,
}
...