Я пытаюсь собрать данные кандидата из таблицы с помощью 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