И выясняем, что паук просто ищет текст между разделителями (запятая) в csv файлах и формирует из них именованные поля Item Fields. Но это еще не все, он пропускает пустые строчки...
In []:
#В предыдущем пауке мне не понравилось то, что вывод
def parse_row(self, response, row):
#log.msg('Hi, this is a row!: %r' % row
"""
ничего не показывал в консоли. Я решил раскомментировать строчку log... но обнаружил,
что снова ничего не происходит. После этого скопировал (и переименовал из "mail_csv" в "mail_csv_2") файл паука,
но обнаружил, что scrapy его не видит !!!
"""
In []:
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>scrapy list
mail_csv
Файл "mail_csv" находится вот в этой папке, там же и новый файл.
In [1]:
!chcp 65001
!dir C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2\scrapy_csv_2\spiders
In []:
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>scrapy genspider -h
Usage
=====
scrapy genspider [options] <name> <domain>
Generate new spider using pre-defined templates
Options
=======
--help, -h show this help message and exit
--list, -l List available templates
--edit, -e Edit spider after creating it
--dump=TEMPLATE, -d TEMPLATE
Dump template to standard output
--template=TEMPLATE, -t TEMPLATE
Uses a custom template.
--force If the spider already exists, overwrite it with the
template
Global Options
--------------
--logfile=FILE log file. if omitted stderr will be used
--loglevel=LEVEL, -L LEVEL
log level (default: DEBUG)
--nolog disable logging completely
--profile=FILE write python cProfile stats to FILE
--lsprof=FILE write lsprof profiling stats to FILE
--pidfile=FILE write process ID to FILE
--set=NAME=VALUE, -s NAME=VALUE
set/override setting (may be repeated)
--pdb enable pdb on failure
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>
In []:
In []:
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>scrapy crawl -h
Usage
=====
scrapy crawl [options] <spider>
Run a spider
Options
=======
--help, -h show this help message and exit
-a NAME=VALUE set spider argument (may be repeated)
--output=FILE, -o FILE dump scraped items into FILE (use - for stdout)
--output-format=FORMAT, -t FORMAT
format to use for dumping items with -o (default:
jsonlines)
Global Options
--------------
--logfile=FILE log file. if omitted stderr will be used
--loglevel=LEVEL, -L LEVEL
log level (default: DEBUG)
--nolog disable logging completely
--profile=FILE write python cProfile stats to FILE
--lsprof=FILE write lsprof profiling stats to FILE
--pidfile=FILE write process ID to FILE
--set=NAME=VALUE, -s NAME=VALUE
set/override setting (may be repeated)
--pdb enable pdb on failure
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>
Ошибка найдена¶
Надо было изменить строчку "name = 'mail_csv_2'" (а я оставил старое имя "mail_csv")
In [2]:
%load "C:\\Users\\kiss\\Documents\\GitMyScrapy\\scrapy_csv_2\\scrapy_csv_2\\spiders\\mail_csv_2.py"
In []:
from scrapy.contrib.spiders import CSVFeedSpider
from scrapy_csv_2.items import ScrapyCsv1Item
from scrapy import log
class MailCsvSpider(CSVFeedSpider):
name = 'mail_csv_2'
#allowed_domains = ['file://C:/Users/kiss/Documents/GitHub_2/scrapy_csv_2/']
#start_urls = ['nissan_9_1_00.csv']
headers = ['N', 'N100', 'purl']
delimiter = ';'
start_urls = ['file://C:/Users/kiss/Documents/GitMyScrapy/scrapy_csv_2/nissan_.csv']
# Do any adaptations you need here
#def adapt_response(self, response):
# return response
def parse_row(self, response, row):
i = ScrapyCsv1Item()
i['N'] = row['N']
i['N100'] = row['N100']
i['purl'] = row['purl']
log.msg('Hi, this is a row!: %r' % row)
return i
In []:
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>scrapy list
mail_csv
mail_csv_2
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>scrapy crawl mail_csv_2
2014-07-23 10:27:21+0400 [scrapy] INFO: Scrapy 0.20.1 started (bot: scrapy_csv_2)
2014-07-23 10:27:21+0400 [scrapy] DEBUG: Optional features available: ssl, http11, boto, django
2014-07-23 10:27:21+0400 [scrapy] DEBUG: Overridden settings: {'NEWSPIDER_MODULE': 'scrapy_csv_2.spiders', 'SPIDER_MODULES': ['scrap
y_csv_2.spiders'], 'BOT_NAME': 'scrapy_csv_2'}
2014-07-23 10:27:22+0400 [scrapy] DEBUG: Enabled extensions: LogStats, TelnetConsole, CloseSpider, WebService, CoreStats, SpiderStat
e
2014-07-23 10:27:23+0400 [scrapy] DEBUG: Enabled downloader middlewares: HttpAuthMiddleware, DownloadTimeoutMiddleware, UserAgentMid
dleware, RetryMiddleware, DefaultHeadersMiddleware, MetaRefreshMiddleware, HttpCompressionMiddleware, RedirectMiddleware, CookiesMid
dleware, ChunkedTransferMiddleware, DownloaderStats
2014-07-23 10:27:23+0400 [scrapy] DEBUG: Enabled spider middlewares: HttpErrorMiddleware, OffsiteMiddleware, RefererMiddleware, UrlL
engthMiddleware, DepthMiddleware
2014-07-23 10:27:23+0400 [scrapy] DEBUG: Enabled item pipelines:
2014-07-23 10:27:23+0400 [mail_csv_2] INFO: Spider opened
2014-07-23 10:27:23+0400 [mail_csv_2] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min)
2014-07-23 10:27:23+0400 [scrapy] DEBUG: Telnet console listening on 0.0.0.0:6023
2014-07-23 10:27:23+0400 [scrapy] DEBUG: Web service listening on 0.0.0.0:6080
2014-07-23 10:27:23+0400 [mail_csv_2] DEBUG: Crawled (200) <GET file://C:/Users/kiss/Documents/GitMyScrapy/scrapy_csv_2/nissan_.csv>
(referer: None)
2014-07-23 10:27:23+0400 [scrapy] INFO: Hi, this is a row!: {'N100': u'N100', 'purl': u'purl', 'N': u'N'}
2014-07-23 10:27:23+0400 [mail_csv_2] DEBUG: Scraped from <200 file://C:/Users/kiss/Documents/GitMyScrapy/scrapy_csv_2/nissan_.csv>
{'N': u'N', 'N100': u'N100', 'purl': u'purl'}
2014-07-23 10:27:23+0400 [scrapy] INFO: Hi, this is a row!: {'N100': u'39,46', 'purl': u'http://auto.mail.ru/catalogue/nissan/', 'N'
: u'7371'}
2014-07-23 10:27:23+0400 [mail_csv_2] DEBUG: Scraped from <200 file://C:/Users/kiss/Documents/GitMyScrapy/scrapy_csv_2/nissan_.csv>
{'N': u'7371',
'N100': u'39,46',
'purl': u'http://auto.mail.ru/catalogue/nissan/'}
2014-07-23 10:27:23+0400 [scrapy] INFO: Hi, this is a row!: {'N100': u'7,58', 'purl': u'http://auto.mail.ru/catalogue/nissan/qashqai
/', 'N': u'1416'}
2014-07-23 10:27:23+0400 [mail_csv_2] DEBUG: Scraped from <200 file://C:/Users/kiss/Documents/GitMyScrapy/scrapy_csv_2/nissan_.csv>
{'N': u'1416',
'N100': u'7,58',
'purl': u'http://auto.mail.ru/catalogue/nissan/qashqai/'}
2014-07-23 10:27:23+0400 [scrapy] INFO: Hi, this is a row!: {'N100': u'6,31', 'purl': u'http://auto.mail.ru/catalogue/nissan/x-trail
/', 'N': u'1179'}
2014-07-23 10:27:23+0400 [mail_csv_2] DEBUG: Scraped from <200 file://C:/Users/kiss/Documents/GitMyScrapy/scrapy_csv_2/nissan_.csv>
{'N': u'1179',
'N100': u'6,31',
'purl': u'http://auto.mail.ru/catalogue/nissan/x-trail/'}
2014-07-23 10:27:23+0400 [mail_csv_2] INFO: Closing spider (finished)
2014-07-23 10:27:23+0400 [mail_csv_2] INFO: Dumping Scrapy stats:
{'downloader/request_bytes': 264,
'downloader/request_count': 1,
'downloader/request_method_count/GET': 1,
'downloader/response_bytes': 218,
'downloader/response_count': 1,
'downloader/response_status_count/200': 1,
'finish_reason': 'finished',
'finish_time': datetime.datetime(2014, 7, 23, 6, 27, 23, 839000),
'item_scraped_count': 4,
'log_count/DEBUG': 11,
'log_count/INFO': 7,
'response_received_count': 1,
'scheduler/dequeued': 1,
'scheduler/dequeued/memory': 1,
'scheduler/enqueued': 1,
'scheduler/enqueued/memory': 1,
'start_time': datetime.datetime(2014, 7, 23, 6, 27, 23, 710000)}
2014-07-23 10:27:23+0400 [mail_csv_2] INFO: Spider closed (finished)
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>
Как сохранить результаты рабты паука?¶
Первый и самый простой - воспользоваться опциями командной строки при вызове паука. Сначала обратим внимание на опции при вызове scrapy crawl -h (они уже распечатаны чуть выше). А вот примеры из документации Simplest way to dump all my scraped items into a JSON/CSV/XML file?
Описания форматов здесь Feed exports
Описания форматов здесь Feed exports
In []:
-a NAME=VALUE set spider argument (may be repeated)
--output=FILE, -o FILE dump scraped items into FILE (use - for stdout)
--output-format=FORMAT, -t FORMAT
format to use for dumping items with -o (default:
jsonlines)
In []:
# Но выполнение такой команды создаст файл со словарями (формат JSON по умолчанию ???)
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>scrapy crawl mail_csv_2 -o items_2.csv
In [4]:
%load "C:\\Users\\kiss\\Documents\\GitMyScrapy\\scrapy_csv_2\\items_2.csv"
In []:
{"purl": "purl", "N100": "N100", "N": "N"}
{"purl": "http://auto.mail.ru/catalogue/nissan/", "N100": "39,46", "N": "7371"}
{"purl": "http://auto.mail.ru/catalogue/nissan/qashqai/", "N100": "7,58", "N": "1416"}
{"purl": "http://auto.mail.ru/catalogue/nissan/x-trail/", "N100": "6,31", "N": "1179"}
Оказывается, что каждая строчка - это словарь. Можно ли записать результаты в обычный csv файл? Попробуем добавить опцию -t csv (--output-format=FORMAT, -t FORMAT) Serialization formats - вот все возможные форматы экспорта со страницы Feed exports
In []:
C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2>scrapy crawl mail_csv_2 -o items_2.csv -t csv
In [5]:
# Оказывается, что результаты этой уточненной команды не стерли предыдущую запись в файле!
%load "C:\\Users\\kiss\\Documents\\GitMyScrapy\\scrapy_csv_2\\items_2.csv"
In []:
{"purl": "purl", "N100": "N100", "N": "N"}
{"purl": "http://auto.mail.ru/catalogue/nissan/", "N100": "39,46", "N": "7371"}
{"purl": "http://auto.mail.ru/catalogue/nissan/qashqai/", "N100": "7,58", "N": "1416"}
{"purl": "http://auto.mail.ru/catalogue/nissan/x-trail/", "N100": "6,31", "N": "1179"}
purl,N100,N
purl,N100,N
http://auto.mail.ru/catalogue/nissan/,"39,46",7371
http://auto.mail.ru/catalogue/nissan/qashqai/,"7,58",1416
http://auto.mail.ru/catalogue/nissan/x-trail/,"6,31",1179
Почему в файл записаны две строчки заголовков? (purl,N100,N) Самое время проверить, как парсятся строки таблиц... Полагаю, что строку заголовка в исходном файле можно убрать.
In []:
C:\Users\kiss\Anaconda\Lib\site-packages\scrapy\contrib\spiders\feed.py
In []:
class CSVFeedSpider(BaseSpider):
"""Spider for parsing CSV feeds.
It receives a CSV file in a response; iterates through each of its rows,
and calls parse_row with a dict containing each field's data.
You can set some options regarding the CSV file, such as the delimiter
and the file's headers.
"""
delimiter = None # When this is None, python's csv module's default delimiter is used
headers = None
def process_results(self, response, results):
"""This method has the same purpose as the one in XMLFeedSpider"""
return results
def adapt_response(self, response):
"""This method has the same purpose as the one in XMLFeedSpider"""
return response
def parse_row(self, response, row):
"""This method must be overriden with your custom spider functionality"""
raise NotImplementedError
def parse_rows(self, response):
"""Receives a response and a dict (representing each row) with a key for
each provided (or detected) header of the CSV file. This spider also
gives the opportunity to override adapt_response and
process_results methods for pre and post-processing purposes.
"""
for row in csviter(response, self.delimiter, self.headers):
ret = self.parse_row(response, row)
if isinstance(ret, (BaseItem, Request)):
ret = [ret]
if not isinstance(ret, (list, tuple)):
raise TypeError('You cannot return an "%s" object from a spider' % type(ret).__name__)
for result_item in self.process_results(response, ret):
yield result_item
def parse(self, response):
if not hasattr(self, 'parse_row'):
raise NotConfigured('You must define parse_row method in order to scrape this CSV feed')
response = self.adapt_response(response)
return self.parse_rows(response)
Да, действительно... Очень слабенький Объект, что с ним делать не ясно...
А вот другой вариант how to use scrapy CSVFeedSpider to crawl a feed that has commas in its values
Пробуем в новом примере код нашего паука, но с исходным файлом без строки-заголовка. И получаем то, что надо:
In [6]:
%load "C:\\Users\\kiss\\Documents\\GitMyScrapy\\scrapy_csv_2\\items_2_2.csv"
In []:
purl,N100,N
http://auto.mail.ru/catalogue/nissan/,"39,46",7371
http://auto.mail.ru/catalogue/nissan/qashqai/,"7,58",1416
http://auto.mail.ru/catalogue/nissan/x-trail/,"6,31",1179
Итак, исходный csv файл должен быть без строки-заголовка. Паук не считывает имена столбцов из первой строчки (как Excel, например), а просто ищет текст между разделителям и формирует словарь с именами заданых нами полей.
Посты чуть ниже также могут вас заинтересовать
Комментариев нет:
Отправить комментарий