Поиск по блогу

среда, 23 июля 2014 г.

Парсим csv файл своим первым MailCsvSpider

И выясняем, что паук просто ищет текст между разделителями (запятая) в 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
Active code page: 65001
 Volume in drive C has no label.
 Volume Serial Number is 6017-2A0B

 Directory of C:\Users\kiss\Documents\GitMyScrapy\scrapy_csv_2\scrapy_csv_2\spiders

23.07.2014  09:25    <DIR>          .
23.07.2014  09:25    <DIR>          ..
23.07.2014  09:22               935 mail_csv.py
23.07.2014  09:22             1В 323 mail_csv.pyc
23.07.2014  09:24               762 mail_csv_2.py
23.07.2014  09:25             1В 012 mail_csv_2.pyc
09.12.2013  15:38               161 __init__.py
10.07.2014  19:30               119 __init__.pyc
               6 File(s)          4В 312 bytes
               2 Dir(s)  394В 055В 471В 104 bytes free

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
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)
Да, действительно... Очень слабенький Объект, что с ним делать не ясно...
Пробуем в новом примере код нашего паука, но с исходным файлом без строки-заголовка. И получаем то, что надо:
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, например), а просто ищет текст между разделителям и формирует словарь с именами заданых нами полей.


Посты чуть ниже также могут вас заинтересовать

Комментариев нет:

Отправить комментарий