Advertisement
tokarevms

New - Shop

Aug 18th, 2017
54
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 7.68 KB | None | 0 0
  1. # coding: utf-8
  2. import requests
  3. from lxml import html
  4. from threading import Thread, Lock
  5. from Queue import Queue
  6. from abc import abstractmethod
  7.  
  8. class MarketSearcher(object):    # Класс поиска в интернет-магазине
  9.  
  10.     def __init__(self, product=''):
  11.         self.product = product.decode('utf-8')
  12.         self._success = None
  13.         self.page = None
  14.         self.result = []
  15.  
  16.     def _check_input(self):    # Проверка непустого ввода
  17.         if not self.product:
  18.             while True:
  19.                 control = (raw_input('Product (type "exit" to exit): ')).decode('utf-8')
  20.                 if control:
  21.                     self.product = control
  22.                     break
  23.  
  24.     def _found_product(self):    # Определение, найден товар в магазине или нет
  25.         respond = requests.get(self._request_params, {'find': self.product,
  26.                                                       'sidx':'price', 'sord':'asc'})
  27.         parsed = html.fromstring(respond.text)
  28.         result = ''.join(parsed.xpath(self._not_found_xpath))
  29.         if self._code_phrase in result:
  30.             print 'Nothing found'
  31.             self._success = None
  32.             return False
  33.         else:
  34.             print 'Product found'
  35.             self._success = parsed
  36.             self.url = respond.url
  37.             return True
  38.  
  39.     def _get_pages_num(self):    # Определение числа страниц товаров в магазине
  40.         try:
  41.             self.page = max(map(int, self._success.xpath(self._pages_xpath)))
  42.         except ValueError:
  43.             self.page = 1
  44.         return self.page
  45.  
  46.     def _parse(self, pages, mutex):    # Запрос и извлечение информации из страницы для многопоточной обработки
  47.         page = pages.get()
  48.         respond = requests.get(self._many_url, {'find': self.product,
  49.                                                 'page': page, 'sidx': 'price',
  50.                                                 'sord': 'asc'})
  51.         parsed = html.fromstring(respond.text)
  52.         name = parsed.xpath(self._many_name_xpath)
  53.         price = parsed.xpath(self._many_price_xpath)
  54.         with mutex:
  55.             self.result.append((name, price))
  56.  
  57.     def _get_result(self):    # Сбор результатов со страниц
  58.         if self._one_product_url in self.url:
  59.             name = self._success.xpath(self._one_name_xpath)
  60.             price = self._success.xpath(self._one_price_xpath)
  61.             self.result = [(name, price)]
  62.             return self.result
  63.         else:    # Если страниц несколько, то распределяет запросы по потокам
  64.             pages = Queue()
  65.             for num in xrange(1, self.page + 1):
  66.                 pages.put(num)
  67.             threads =[]
  68.             lock = Lock()
  69.             for i in xrange(self.page if self.page <= 12 else 12):
  70.                 thread = Thread(target=self._parse, args=(pages, lock))
  71.                 thread.start()
  72.                 threads.append(thread)
  73.             for thread in threads:
  74.                 thread.join()
  75.             return self.result
  76.  
  77.     def _output(self):    # Вывод в файл
  78.         with open('Result.txt', 'w') as file:
  79.             for number, page in enumerate(self.result):
  80.                 file.write('\n\nPage %-100s\t\n\n' % (number + 1))
  81.                 for item in zip(*page):
  82.                     file.write(('%-100s\t%s\n' % (item[0], item[1])).encode('cp1251'))
  83.  
  84.     def _end_search(self):    # Окончание поиска
  85.         self.result = []
  86.         self.page = None
  87.         self._success = None
  88.         self.product = ''
  89.  
  90.     @abstractmethod
  91.     def start(self):    # Последовательность действий для поиска
  92.         while True:
  93.             self._check_input()
  94.             if self.product != 'exit':
  95.                 if self._found_product():
  96.                     self._get_pages_num()
  97.                     self._get_result()
  98.                     self._output()
  99.                 self._end_search()
  100.             else:
  101.                 break
  102.  
  103.  
  104. class TopShopSearch(MarketSearcher):    # Класс поиска в Top-Shop
  105.  
  106.     def __init__(self, product=''):    # Параметры для формирования запрсоов и сбора информации
  107.         MarketSearcher.__init__(self, product)
  108.         self.market = self.url = 'http://www.top-shop.ru/'
  109.         self._request_params = self.market + 'search/'
  110.         self._not_found_xpath = '//div[@class="result_text"]/text()'
  111.         self._code_phrase = 'мы не нашли товаров'.decode('utf-8')
  112.         self._pages_xpath = '//li[@class=" js_page"]/@data-num'
  113.         self._one_product_url = '/product/'
  114.         self._one_name_xpath = '//body/div[6]/div[2]/div/div/div/div/h1/text()'
  115.         self._one_price_xpath = '//body/div[6]/div[3]/div[3]/div/div[2]/div/div[1]/text()'
  116.         self._many_url = self.market + 'search/'
  117.         self._many_name_xpath = '//span[@class="hidden js_ectrack"]/@data-name'
  118.         self._many_price_xpath = '//span[@class="hidden js_ectrack"]/@data-price'
  119.  
  120.  
  121. class EldoShopSearch(MarketSearcher):    # Посик в интернет-магазине Эльдорадо
  122.  
  123.     def __init__(self, product=''):    # Параметры
  124.         MarketSearcher.__init__(self, product)
  125.         self.market = self.url = 'http://www.eldorado.ru/'
  126.         self._request_params = self.market + 'search/catalog.php'
  127.         self._not_found_xpath = '//p[@class="paragraph searchInfoTitle"]/text()'
  128.         self._code_phrase = 'ничего не найдено'.decode('utf-8')
  129.         self._pages_xpath = '//div[@class="pages"]/a/text()'
  130.         self._one_product_url = '/cat/detail'
  131.         self._one_name_xpath = '//h1[@itemprop="name"]/text()'
  132.         self._one_price_xpath = '//td/span[@itemprop="price"]/text()'
  133.         self._many_url = self.market + 'search/catalog.php'
  134.         self._many_name_xpath = '//div[@class="itemDescription"]/div[@class="itemTitle"]/a/text()'
  135.         self._many_price_xpath = '//div[@class="priceContainer"]/div/span[@class="discountPrice itemPrice"]/text()'
  136.  
  137.     def _parse(self, pages, mutex):    # Переопределен запрос для многопоточной обработки
  138.         page = pages.get()
  139.         respond = requests.get(self._many_url, {'q': self.product,
  140.                                                 'page': page, 'sort': 'price',
  141.                                                 'type': 'asc',
  142.                                                 "list_num" : 50})
  143.         parsed = html.fromstring(respond.text)
  144.         name = parsed.xpath(self._many_name_xpath)
  145.         price = parsed.xpath(self._many_price_xpath)
  146.         with mutex:
  147.             self.result.append((name, price))
  148.  
  149.     def _found_product(self):    # Переопределено определение успешности поиска
  150.         respond = requests.get(self._request_params, {'q': self.product,
  151.                                                       'sort':'price', 'type':'asc',
  152.                                                       'list_num': 50})
  153.         parsed = html.fromstring(respond.text)
  154.         result = ''.join(parsed.xpath(self._not_found_xpath))
  155.         if self._code_phrase in result:
  156.             print 'Nothing found'
  157.             self._success = None
  158.             return False
  159.         else:
  160.             print 'Product found'
  161.             self._success = parsed
  162.             self.url = respond.url
  163.             return True
  164.  
  165.  
  166. if __name__ == '__main__':
  167.     first = TopShopSearch()
  168.     first.start()
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement