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

суббота, 3 января 2015 г.

Срочно пишем простого паука carmailPrice со scrapy genspider для того, чтобы увековечить цены на все автомобили

Здесь я повторяю процессы startproject, genspider, ... потом пишем паука со списком начальных URI, добавляем в него def parse(...) с итератором по ссылкам на html-странице. здесь и список ссылок. Вариант работающий на локальном компьютере, но промежуточный. Понадобится, как учебный пример...

In []:
[genspider](http://doc.scrapy.org/en/latest/topics/commands.html?highlight=scrapy%20genspider#genspider)

1. Создаем проект

In [1]:
!scrapy startproject -h 
Usage
=====
  scrapy startproject <project_name>

Create new project

Options
=======
--help, -h              show this help message and exit

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

In []:
# Эта команда создает папку проекта с подпапками
C:\Users\kiss\SkyDrive\Docs\mailru\cars_mail_1>scrapy startproject carmailPrice

2. Заходим в папку проекта и генерируем паука

In []:
C:\Users\kiss\SkyDrive\Docs\mailru\cars_mail_1\carmailPrice>scrapy genspider price cars.mail.ru
Created spider 'price' using template 'crawl' in module:
  carmailPrice.spiders.price

Я думал, что по умолчанию используется шаблон 'basic', нет, оказывается, что более крутой 'crawl'

In []:
C:\Users\kiss\SkyDrive\Docs\mailru\cars_mail_1\carmailPrice>tree /F
Структура папок
Серийный номер тома: 000000D1 6017:2A0B
C:.
   scrapy.cfg

└───carmailPrice
       items.py
       pipelines.py
       settings.py
       settings.pyc
       __init__.py
       __init__.pyc
    
    └───spiders
            price.py
            __init__.py
            __init__.pyc
In [6]:
%load "C:\\Users\\kiss\\SkyDrive\\Docs\\mailru\\cars_mail_1\\carmailPrice\\carmailPrice\\spiders\\price.py"
In []:
from scrapy.selector import HtmlXPathSelector
from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor
from scrapy.contrib.spiders import CrawlSpider, Rule
from carmailPrice.items import CarmailpriceItem

class PriceSpider(CrawlSpider):
    name = 'price'
    allowed_domains = ['cars.mail.ru']
    start_urls = ['http://www.cars.mail.ru/']

    rules = (
        Rule(SgmlLinkExtractor(allow=r'Items/'), callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        hxs = HtmlXPathSelector(response)
        i = CarmailpriceItem()
        #i['domain_id'] = hxs.select('//input[@id="sid"]/@value').extract()
        #i['name'] = hxs.select('//div[@id="name"]').extract()
        #i['description'] = hxs.select('//div[@id="description"]').extract()
        return i

Вот такая заготовочка получилась. Читаем документацию, а там не рекомендуется использовать этот класс... SgmlLinkExtractor Я в цейтноте, потому посмотрим более простой вариант. А этот перенесем на начало следующего года.

Сгенерируем паучка попроще

In []:
C:\Users\kiss\SkyDrive\Docs\mailru\cars_mail_1\carmailPrice>scrapy genspider -t basic price_1 cars.mail.ru
Created spider 'price_1' using template 'basic' in module:
  carmailPrice.spiders.price_1
In [7]:
%load "C:\\Users\\kiss\\SkyDrive\\Docs\\mailru\\cars_mail_1\\carmailPrice\\carmailPrice\\spiders\\price_1.py"
In []:
from scrapy.spider import BaseSpider

class Price1Spider(BaseSpider):
    name = "price_1"
    allowed_domains = ["cars.mail.ru"]
    start_urls = (
        'http://www.cars.mail.ru/',
        )

    def parse(self, response):
        pass 

В кортеж с начальными start_urls вставим ссылки, которые я напарсил раньше для других целей при помощи плагина XPart Helper Chrome. Он помимо прочего еще и дуби убирае т, потому просто вставляем в левое поле этот запрос и получаем список. Потом в редакторе добавим базовый url и кавычки. Итог в приложении (Приложение №1 в конце поста).

In []:
//div[@class='tile-pin-list tile-pin-list_catalog']/a[@class='tile-pin']/@href

Итератор селекторов на каждой странице фирмы.

После того, как паук переползет на страницу фирмы, ему нужно найти все модели, точнее их НАЗВАНИЯ, Названия в ссылках, ЦЕНУ. Поведение нашего паука очень похоже на примерного паука DMOZ. Скопируем сначала DMOZ:

In [8]:
%load 'C:\\Users\\kiss\\Documents\\GitHub\\dirbot\\dirbot\\spiders\\dmoz.py'
In []:
from scrapy.spider import BaseSpider
from scrapy.selector import HtmlXPathSelector

from dirbot.items import Website


class DmozSpider(BaseSpider):
    name = "dmoz"
    allowed_domains = ["dmoz.org"]
    start_urls = [
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Books/",
        "http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/",
    ]

    def parse(self, response):
        """
        The lines below is a spider contract. For more info see:
        http://doc.scrapy.org/en/latest/topics/contracts.html

        @url http://www.dmoz.org/Computers/Programming/Languages/Python/Resources/
        @scrapes name
        """
        hxs = HtmlXPathSelector(response)
        sites = hxs.select('//ul[@class="directory-url"]/li')
        items = []

        for site in sites:
            item = Website()
            item['name'] = site.select('a/text()').extract()
            item['url'] = site.select('a/@href').extract()
            item['description'] = site.select('text()').re('-\s([^\n]*?)\\n')
            items.append(item)

        return items

А у меня получился вот такой итератор... каждый оператор я проверил в Scrapy shell (Приложение №2).

In []:
for sel in sel.css('.catalog-generation__card'):
    title = sel.xpath('.//a[@class="catalog-generation__card__title"]/text()').extract()
    link = sel.xpath('.//a[@class="catalog-generation__card__title"]/@href').extract()
    price = sel.xpath('.//span[@class="rank"]/i/text()').extract()
    print title, link, price

Нам нужно импортировать класс для работы с CSS

In [9]:
import scrapy.selector
In [10]:
dir(scrapy.selector)
Out[10]:
['HtmlXPathSelector',
 'Selector',
 'SelectorList',
 'XPathSelector',
 'XPathSelectorList',
 'XmlXPathSelector',
 '__builtins__',
 '__doc__',
 '__file__',
 '__name__',
 '__package__',
 '__path__',
 'csstranslator',
 'lxmldocument',
 'lxmlsel',
 'unified']
In []:
from scrapy.spider import BaseSpider
from scrapy.selector import Selector

from carmailPrice.items import CarmailpriceItem
#from lists_unitial_urls.car_mail_catalog_url import start_urls_list

class Price1Spider(BaseSpider):
 name = "price_1"
 allowed_domains = ["cars.mail.ru"]
 start_urls = [
  #'http://www.cars.mail.ru/catalog',
  'file://C:/Users/kiss/Desktop/carsmail/carsmail/cars.mail.ru/catalog/bmw/index.html',
  ]

 def parse(self, response):
  hxs = Selector(response)
  firm_list = hxs.css('.catalog-generation__card')
  items = []
    
  for sel in firm_list:
   item = CarmailpriceItem() 
   item['name'] = sel.xpath('.//a[@class="catalog-generation__card__title"]/text()').extract()
   item['link'] = sel.xpath('.//a[@class="catalog-generation__card__title"]/@href').extract()
   item['price'] = sel.xpath('.//span[@class="rank"]/i/text()').extract()
   items.append(item)
    from scrapy.spider import BaseSpider
from scrapy.selector import Selector

from carmailPrice.items import CarmailpriceItem
#from lists_unitial_urls.car_mail_catalog_url import start_urls_list

class Price1Spider(BaseSpider):
 name = "price_1"
 allowed_domains = ["cars.mail.ru"]
 start_urls = [
  #'http://www.cars.mail.ru/catalog',
  'file://C:/Users/kiss/Desktop/carsmail/carsmail/cars.mail.ru/catalog/bmw/index.html',
  ]

 def parse(self, response):
  hxs = Selector(response)
  firm_list = hxs.css('.catalog-generation__card')
  items = []
    
  for sel in firm_list:
   item = CarmailpriceItem() 
   item['name'] = sel.xpath('.//a[@class="catalog-generation__card__title"]/text()').extract()
   item['link'] = sel.xpath('.//a[@class="catalog-generation__card__title"]/@href').extract()
   item['price'] = sel.xpath('.//span[@class="rank"]/i/text()').extract()
   items.append(item)
        
  return items 
 #import ipdb; ipdb.set_trace()    
 return items 

Этот вариант паука отладочный, он прекрасно работает, а окончательный будет здесь на w8 C:\Users\kiss\SkyDrive\Docs\mailru\cars_mail_1\carmailPrice

Приложение №1

In []:
'https://cars.mail.ru/catalog/acura/',
'https://cars.mail.ru/catalog/audi/',
'https://cars.mail.ru/catalog/bentley/',
'https://cars.mail.rucatalog/bmw/',
'https://cars.mail.ru/catalog/cadillac/',
'https://cars.mail.ru/catalog/chery/',
'https://cars.mail.ru/catalog/chevrolet/',
'https://cars.mail.ru/catalog/chrysler/',
'https://cars.mail.ru/catalog/citroen/',
'https://cars.mail.ru/catalog/daewoo/',
'https://cars.mail.ru/catalog/datsun/',
'https://cars.mail.ru/catalog/faw/',
'https://cars.mail.ru/catalog/ferrari/',
'https://cars.mail.ru/catalog/fiat/',
'https://cars.mail.ru/catalog/ford/',
'https://cars.mail.ru/catalog/geely/',
'https://cars.mail.ru/catalog/great_wall/',
'https://cars.mail.ru/catalog/honda/',
'https://cars.mail.ru/catalog/hyundai/',
'https://cars.mail.ru/catalog/infiniti/',
'https://cars.mail.ru/catalog/jaguar/',
'https://cars.mail.ru/catalog/jeep/',
'https://cars.mail.ru/catalog/kia/',
'https://cars.mail.ru/catalog/lada_vaz/',
'https://cars.mail.ru/catalog/lamborghini/',
'https://cars.mail.ru/catalog/land_rover/',
'https://cars.mail.ru/catalog/lexus/',
'https://cars.mail.ru/catalog/luxgen/',
'https://cars.mail.ru/catalog/mazda/',
'https://cars.mail.ru/catalog/mercedes-benz/',
'https://cars.mail.ru/catalog/mini/',
'https://cars.mail.ru/catalog/mitsubishi/',
'https://cars.mail.ru/catalog/nissan/',
'https://cars.mail.ru/catalog/opel/',
'https://cars.mail.ru/catalog/peugeot/',
'https://cars.mail.ru/catalog/porsche/',
'https://cars.mail.ru/catalog/renault/',
'https://cars.mail.ru/catalog/seat/',
'https://cars.mail.ru/catalog/skoda/',
'https://cars.mail.ru/catalog/smart/',
'https://cars.mail.ru/catalog/ssangyong/',
'https://cars.mail.ru/catalog/subaru/',
'https://cars.mail.ru/catalog/suzuki/',
'https://cars.mail.ru/catalog/tesla/',
'https://cars.mail.ru/catalog/toyota/',
'https://cars.mail.ru/catalog/volkswagen/',
'https://cars.mail.ru/catalog/volvo/',
'https://cars.mail.ru/catalog/uaz/',
'https://cars.mail.ru/catalog/acura/',
'https://cars.mail.ru/catalog/daihatsu/',
'https://cars.mail.ru/catalog/datsun/',
'https://cars.mail.ru/catalog/honda/',
'https://cars.mail.ru/catalog/infiniti/',
'https://cars.mail.ru/catalog/lexus/',
'https://cars.mail.ru/catalog/mazda/',
'https://cars.mail.ru/catalog/mitsubishi/',
'https://cars.mail.ru/catalog/nissan/',
'https://cars.mail.ru/catalog/scion/',
'https://cars.mail.ru/catalog/subaru/',
'https://cars.mail.ru/catalog/suzuki/',
'https://cars.mail.ru/catalog/toyota/',
'https://cars.mail.ru/catalog/buick/',
'https://cars.mail.ru/catalog/cadillac/',
'https://cars.mail.ru/catalog/chevrolet/',
'https://cars.mail.ru/catalog/chrysler/',
'https://cars.mail.ru/catalog/dodge/',
'https://cars.mail.ru/catalog/ford/',
'https://cars.mail.ru/catalog/gmc/',
'https://cars.mail.ru/catalog/hummer/',
'https://cars.mail.ru/catalog/jeep/',
'https://cars.mail.ru/catalog/lincoln/',
'https://cars.mail.ru/catalog/mercury/',
'https://cars.mail.ru/catalog/oldsmobile/',
'https://cars.mail.ru/catalog/pontiac/',
'https://cars.mail.ru/catalog/tesla/',
'https://cars.mail.ru/catalog/lada_vaz/',
'https://cars.mail.ru/catalog/gaz/',
'https://cars.mail.ru/catalog/moskvich/',
'https://cars.mail.ru/catalog/tagaz/',
'https://cars.mail.ru/catalog/uaz/',
'https://cars.mail.ru/catalog/audi/',
'https://cars.mail.ru/catalog/bmw/',
'https://cars.mail.ru/catalog/mercedes-benz/',
'https://cars.mail.ru/catalog/opel/',
'https://cars.mail.ru/catalog/porsche/',
'https://cars.mail.ru/catalog/volkswagen/',
'https://cars.mail.ru/catalog/daewoo/',
'https://cars.mail.ru/catalog/hyundai/',
'https://cars.mail.ru/catalog/kia/',
'https://cars.mail.ru/catalog/ssangyong/',
'https://cars.mail.ru/catalog/alfa_romeo/',
'https://cars.mail.ru/catalog/aston_martin/',
'https://cars.mail.ru/catalog/bentley/',
'https://cars.mail.ru/catalog/bugatti/',
'https://cars.mail.ru/catalog/citroen/',
'https://cars.mail.ru/catalog/ferrari/',
'https://cars.mail.ru/catalog/fiat/',
'https://cars.mail.ru/catalog/jaguar/',
'https://cars.mail.ru/catalog/lamborghini/',
'https://cars.mail.ru/catalog/lancia/',
'https://cars.mail.ru/catalog/land_rover/',
'https://cars.mail.ru/catalog/maserati/',
'https://cars.mail.ru/catalog/maybach/',
'https://cars.mail.ru/catalog/mini/',
'https://cars.mail.ru/catalog/peugeot/',
'https://cars.mail.ru/catalog/renault/',
'https://cars.mail.ru/catalog/rolls-royce/',
'https://cars.mail.ru/catalog/rover/',
'https://cars.mail.ru/catalog/saab/',
'https://cars.mail.ru/catalog/seat/',
'https://cars.mail.ru/catalog/skoda/',
'https://cars.mail.ru/catalog/volvo/',
'https://cars.mail.ru/catalog/brilliance/',
'https://cars.mail.ru/catalog/byd/',
'https://cars.mail.ru/catalog/changan/',
'https://cars.mail.ru/catalog/chery/',
'https://cars.mail.ru/catalog/dongfeng/',
'https://cars.mail.ru/catalog/faw/',
'https://cars.mail.ru/catalog/geely/',
'https://cars.mail.ru/catalog/haima/',
'https://cars.mail.ru/catalog/haval/',
'https://cars.mail.ru/catalog/jac/',
'https://cars.mail.ru/catalog/lifan/',
'https://cars.mail.ru/catalog/luxgen/',

Приложение №2 (проверка в shell)

In []:
In [44]: ss.xpath('.//span[@class="rank"]/i/text()').extract()
Out[44]: [u'1', u'104', u'000']

In [45]: ss.xpath('.//a[@class="catalog-generation__card__title"]/text()').extract()
Out[45]: [u'\n BMW 1\n \u043a\u0443\u043f\u0435\n ']

In [46]: ss.xpath('.//a[@class="catalog-generation__card__title"]/@href').extract()
Out[46]: [u'/catalog/bmw/1/e82/coupe/']


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

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

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