Паук Scrapy не выполняет итерацию правильно и имеет проблему с оператором If - PullRequest
0 голосов
/ 09 июня 2018

Я пытаюсь собрать данные кандидата из таблицы с помощью Scrapy.У меня две проблемы:

1) Я хочу CSV с каждым кандидатом в каждой строке:

'username': ['clickclack123'],'lsat':['170'],'gpa':['3.57']... 

Мой код в настоящее время извлекает все данные кандидата в одной строке, игнорируя нользначений и повторяет это извлечение для количества кандидатов на странице (100 одинаковых строк, где каждая строка содержит все данные на странице):

'username': ['clickclack123','UM2014','3litersaday'...

2) Таблица содержит класс элементов («означающие»), которые указывают черты заявителя.Я хочу включить оператор If, чтобы проверить значение и сохранить каждую черту как True, если применимо.Я включил оператор If с этой логикой в ​​lawschool.py (ниже), но он не позволяет моему пауку бежать.

Мои мысли и попытки:

  • ДляПроблема № 1, я видел сообщения с похожими проблемами, но эти решения не работали в этом случае, потому что мои данные содержат нулевые значения, которые я не хочу игнорировать.
  • Я считаю, что есть проблема с моим Forцикл, потому что он не выполняет итерацию должным образом для каждого кандидата, но я не смог это исправить.В настоящее время он извлекает все данные на странице в одну строку моего CSV, но повторяет это извлечение для количества кандидатов на странице (100 одинаковых строк, где каждая строка содержит все данные на странице).Если я изменю extract () на extract_first (), паук будет извлекать данные только для первого заявителя (100 одинаковых строк, где каждая строка содержит данные от первого заявителя).
  • Для проблемы № 2 яЯ не уверен, почему мой код не запускается с этим оператором If, и мне пришлось закомментировать его для устранения проблемы # 1.

lawschool.py

import scrapy
from ..items import ApplicantItem

class LawschoolSpider(scrapy.Spider):
    name = "lawschool"
    start_urls = [
        'http://nyu.lawschoolnumbers.com/applicants',
        'http://columbia.lawschoolnumbers.com/applicants'
    ]

    def parse(self, response):
        items = []
        for applicant in response.xpath("//tr[@class='row']"):
            signifier = response.xpath("//span[@class='signifier']/text()").extract()
            if signifier == 'W':
                withdrawn = True
            elif signifier == 'A':
                accepted == True
            elif signifier == 'U':
                minority == True
            elif signifier == 'N':
                non_traditional == True
            elif signifier == 'I':
                international = True
            else:
                return False
            school = response.xpath("//h1/text()").extract()
            school = [i.replace(' Applicants','') for i in school]
            item = ApplicantItem(
                school = school,
                username = response.xpath("//td/a/text()").extract(),
                lsat = response.xpath("//td[contains(@style, 'font-weight:bold')]/following-sibling::td[1]/text()").extract(),
                gpa = response.xpath("//td[contains(@style, 'font-weight:bold')]/following-sibling::td[2]/text()").extract(),
                scholarship = response.xpath("//td[contains(@style, 'font-weight:bold')]/following-sibling::td[4]/text()").extract(),
                status = response.xpath("//td[contains(@style, 'font-weight:bold')]/following-sibling::td[5]/text()").extract(),
                sent = response.xpath("//td[contains(@style, 'font-weight:bold')]/following-sibling::td[6]/text()").extract(),
                complete = response.xpath("//td[contains(@style, 'font-weight:bold')]/following-sibling::td[7]/text()").extract(),
                decision = response.xpath("//td[contains(@style, 'font-weight:bold')]/following-sibling::td[8]/text()").extract(),
                last_updated = response.xpath("//td[contains(@style, 'font-weight:bold')]/following-sibling::td[9]/text()").extract()
                withdrawn_application = withdrawn,
                accepted_offer = accepted,
                minority = minority,
                non_traditional = non_traditional,
                international = international
            )
            yield item

        for a in response.xpath("//*[@id='applicants_list']/div/a[9]"):
            yield response.follow(a, callback=self.parse)

items.py

from scrapy import Item, Field


class ApplicantItem(Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    school = Field()
    username = Field()
    lsat = Field()
    gpa = Field()
    scholarship = Field()
    status = Field()
    sent = Field()
    complete = Field()
    decision = Field()
    last_updated = Field()
    withdrawn_application = Field()
    accepted_offer = Field()
    minority = Field()
    non_traditional = Field()
    international = Field()

pipe.py

from scrapy import signals
from scrapy.exporters import CsvItemExporter

from .items import ApplicantItem

class LSNPipeline(object):

    @classmethod
    def from_crawler(cls, crawler):
        pipeline = cls()
        crawler.signals.connect(pipeline.spider_opened, signals.spider_opened)
        crawler.signals.connect(pipeline.spider_closed, signals.spider_closed)
        return pipeline

    def spider_opened(self, spider):
        item_names = ['applicant']
        self.files = self.files = {n: open('%s.csv' % n, 'w+b') for n in item_names}
        self.exporters = {n: CsvItemExporter(f) for n, f in self.files.items()}
        for exporter in self.exporters.values():
            exporter.start_exporting()

    def spider_closed(self, spider):
        for exporter in self.exporters.values():
            exporter.finish_exporting()

        for file in self.files.values():
            file.close()

    def process_item(self, item, spider):
        if isinstance(item, ApplicantItem):
            self.exporters['applicant'].export_item(item)

        return item

1 Ответ

0 голосов
/ 09 июня 2018

Вам нужно относительно выражений XPath:

username = applicant.xpath(".//td/a/text()").extract(),
lsat = applicant.xpath(".//td[2]/text()").extract(),
gpa = applicant.xpath(".//td[3]/text()").extract(),
...
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...