Форум сайта python.su
0
ребят, подскажите пожалуйста как писать парсеры
я вот набросал для примера парсер(букв много, но программу читать не надо, вопрос по организации кода). но одолевают меня сомнения. как ни старался код не дублировать, всё таки получилась программа трудная для чтения. и дело не в том, что используется процедурный стиль. я уверен, что можно организовать код более красиво
если это возможно, то объясните пожалуйста кратко на словах где я не прав и что можно улучшить. или парсеры такие и должны быть и этот вполне нормальный?
ещё раз повторюсь, что вопрос не по программе, а именно по способу организации кода
# win7 pithon33 import pprint import requests import lxml.etree import lxml.html import lxml.cssselect import re import os import sys import shutil import urllib def get_doc(url): try: req = requests.get(url) except Exception: print('Error open. __', Exception) else: html = req.text doc = lxml.html.document_fromstring(html) return doc def record_xml(xml, fileName='xml.xml'): try: with open(fileName, "w") as file: file.write(xml) except Exception: print('Error record', Exception) else: print('record ok') def get_list_pages(doc): listPages = [] #listPages = doc.xpath('//table//td[@class="pages"]/a') listLinks = doc.cssselect('table.pagn td.pages a') for elem in listLinks: href = elem.get('href') listPages.append(href) if not listPages: print('Error forming list pages') else: return listPages def get_list_goods(listPages): listGoodsLinks = [] #i = 0 for path in listPages: doc = get_doc(path) listGoods = doc.xpath('//div[@id="ResultSetItems"]/table//h3/a') #i = i + 1 #if i > 1: break for elem in listGoods: href = elem.get('href') listGoodsLinks.append(href) if not listGoodsLinks: print('Error forming list goods') else: return listGoodsLinks def get_info(listGoodsLinks): #i = 0 result = {} for url in listGoodsLinks: doc = get_doc(url) try: title = doc.xpath('//h1[@id="itemTitle"]/text()')[0].strip() except Exception: title = 'None' try: priceUSD = [t.replace('\xa0', ' ') for t in doc.xpath('//span[@itemprop="price"]/text()')] or [t.replace('\xa0', ' ') for t in doc.xpath('//span[@id="mm-saleDscPrc"]/text()')] priceUSD = priceUSD[0] #search = re.search('([\d, ]+)$', priceUSD) #priceUSD = search.group(1) priceUSD = priceUSD.replace('US $', '') except Exception: priceUSD = 'None' try: priceRUR = [t.replace('\xa0', ' ') for t in doc.xpath('//div[@id="prcIsumConv"]/span/text()')] priceRUR = priceRUR[0] priceRUR = priceRUR.replace(u' руб', '') except Exception: priceRUR = 'None' try: condition = doc.xpath('//div[@id="vi-itm-cond"]/text()')[0].strip() except Exception: condition = 'None' try: timeLeft = doc.xpath('//span[@id="vi-cdown_timeLeft"]/text()')[0].strip() except Exception: timeLeft = 'None' try: sellerName = doc.xpath('//span[@class="mbg-nw"]/text()')[0].strip() except Exception: sellerName = 'None' try: salesQuantity = doc.xpath('//span[@class="mbg-l"]/a/text()')[0].strip() except Exception: salesQuantity = 'None' print(title, priceUSD, priceRUR, condition, timeLeft, url, sellerName, salesQuantity, end='\n\n') listImages = [] thumbs = doc.xpath('//td[@class="tdThumb"]/div/img') for thumb in thumbs: thumbSrc = thumb.get('src') #print(thumbSrc) imageSrc = thumbSrc.replace('_39', '_57') #print(imageSrc) listImages.append(imageSrc) info = { 'title': title, 'price_usd': priceUSD, 'price_rur': priceRUR, 'condition': condition, 'time_left': timeLeft, 'seller_name': sellerName, 'sales_quantity': salesQuantity, 'imagesWeb': listImages } result[url] = info newCatalog = create_dir(title) for imgPath in listImages: download_image(imgPath, catalog=newCatalog) #i = i + 1 #if i > 2: break return result def create_dir(title): title = secureChars(title) newCatalog = make_catalog(title) return newCatalog def make_catalog(catalog): try: os.mkdir(catalog) except Exception as ex: print(Exception, ex) else: return catalog def change_catalog(catalog): try: os.chdir(catalog) except Exception as ex: print(Exception, ex) else: return True def make_elements(info): parent = lxml.etree.Element('data') for url in sorted(info): child = lxml.etree.Element('item', href=url) for key, value in info[url].items(): if type(value) == list: child2 = lxml.etree.Element(key) for val in value: child3 = lxml.etree.Element('image') child3.text = val child2.append(child3) child.append(child2) parent.append(child) else: child2 = lxml.etree.Element(key) child2.text = value child.append(child2) parent.append(child) return parent def ready_os(catalog): for rootdir, dirnames, filenames in os.walk(catalog): #print(rootdir, '==') for subdirname in dirnames: try: dirName = os.path.join(rootdir, subdirname) except Exception as exc: print(exc) sys.exit() else: print(dirName) shutil.rmtree(dirName) for filename in filenames: try: fileName = os.path.join(rootdir, filename) except Exception as exc: print(exc) sys.exit() else: print(fileName) os.remove(fileName) if os.path.exists(catalog): print('warning. catalog exists') #чистим каталог for the_file in os.listdir(catalog): file_path = os.path.join(catalog, the_file) try: if os.path.isfile(file_path): os.unlink(file_path) except Exception as exc: print(exc) sys.exit() else: dataCatalog = make_catalog(catalog) if not dataCatalog: print('error catalog create') sys.exit() if not change_catalog(catalog): print('error change catalog') sys.exit() return def download_image(path, catalog): img = urllib.request.urlopen(path).read() search = re.search('.*\/(.+?)\/(.+?)\.(.+)$', path) name = search.group(1) ext = search.group(3) name = secureChars(name) ext = secureChars(ext) realPath = os.getcwd() fullPath = os.path.join(realPath, catalog, name + '.' + ext) with open(fullPath, "wb") as f: f.write(img) def secureChars(word): replace_chars = ['\\', '/', ':', '*', '?', '"', '<', '>', '|', '-' , ' ', '!'] for char in replace_chars: word = word.replace(char, '_') return word if __name__ == "__main__": url = 'http://ebay.com/' query = 'http://www.ebay.com/sch/i.html?_sacat=0&_nkw=dw+drum+set&_frs=1' doc = get_doc(query) catalog = 'data' #готовим каталог, в котором будут храниться скачанные данные ready_os(catalog) #получаем набор линков страниц с товарами listPages = get_list_pages(doc) pprint.pprint(listPages) #получаем набор линков на страницы конкретного товара listGoodsLinks = get_list_goods(listPages) pprint.pprint(listGoodsLinks) #получаем набор данных для info = get_info(listGoodsLinks) #строим xml-дерево xml = make_elements(info) xmlPretty = lxml.etree.tounicode(xml, pretty_print=True) print(xmlPretty) #запись xml в текстовый файл record_xml(xmlPretty, 'ebay.xml')
Отредактировано zlodiak (Март 4, 2014 21:56:25)
Офлайн
103
Я хочу познать Дао программирования, но мне впадло думать! Я хочу зарабатывать много денег, но вместо того чтобы думать, я напишу на форум, пусть поправят мой код, чтобы он был красивым! Ведь на форумах сидят люди, которым больше нечем заняться, кроме как исправлять чужой код, длиной в 250 строк!
Вы хотите писать красивый код, а что вы для этого сделали? написали на форум???
Я могу исправить ошибку, показать правильный путь, подсказать какойто модуль и т.д. НО тратить полчаса на улучшения программы!….
Я отвечаю на вопросы, чтобы помочь человеку стать лучше, он пытается чтото сделать сам, ищет, но не может найти или нашел, но не работает и прибегает к помощьи людей, которые возможно встречали данную ошибку или внимательней читали документацию. А вы… Я не могу понять, что вы думали, когда писали такое???
набросал для примера парсер(букв много, но программу читать не надо, вопрос по организации кода)А, извините, я не увидел, как же я сразу не понял, что здесь всегото нужно приложить ладоню к экрану и экстрасенсорными сбособностями увидеть бегло написанный код)))
или парсеры такие и должны быть и этот вполне нормальный?НЕТ! смотря какой сайт, и смотря что вам нужно. У меня есть парсер на 50 строк, а есть парсер для большого збора и анализа информации на 600 строк. НО, я никому не писал, посмотрите на мой код, не читайте все 600 строк, просто скажите, я молодец?
ещё раз повторюсь, что вопрос не по программе, а именно по способу организации кода
как ни старался код не дублировать, всё таки получилась программа трудная для чтения.как я могу улучшить код, не вникая в него, как я могу показать вам как не дублировать код, не читая его?!
Отредактировано terabayt (Март 4, 2014 22:47:25)
Офлайн
Резко высказались, человек не Вам домой письмо прислал. День не сложился? А может, кто за чашечкой кофе что и полезного ответит, это ж форум. Он не наглеет, не попрошайничает, по-нормальному спросил, чего Вы?
Офлайн
103
dimy44Да, спасибо, день - дерьмо! Может и резко, но немного нравоучений не помешает. И такие же потом на работу идут. Я уже четвертый день пытаюсь решить неришимую проблему и с каждым днем все хуже и хуже. Просто, если сейчас не наставить на правильный путь, то потом, придя на работу, ему будет очень сложно! Ненавижу работать “в команде”!!!!!!
Отредактировано terabayt (Март 5, 2014 01:28:22)
Офлайн
103
zlodiakЕсли хотите писать красивый код, нужно:
Офлайн
221
zlodiakможно поменять на “конвейрный” прием
priceRUR = [t.replace('\xa0', ‘ ’) for t in doc.xpath('//div/span/text()')]
priceRUR = priceRUR
priceRUR = priceRUR.replace(u' руб', '')
priceRUR = [t.replace('\xa0', ' ') for t in doc.xpath('//div[@id="prcIsumConv"]/span/text()')][0].replace(u' руб', '')[/quote]
terabaytесли вам полегчает, то вы не один такой, я тоже, бьюсь над проблемой из разряда “в доках написано” в одном случае код работает в другом тот же не работает. жизнь…она такая.. приходится упорно решать проблемы
Я уже четвертый день пытаюсь решить неришимую проблему и с каждым днем все хуже и хуже.
Офлайн
19
Не рекомендуется для названия переменных использовать mountain style. Лучше так link_list. При этом сначала пишем сущность link затем принадлежность list.
listLinksНикогда не нужно отлавливать все исключения, ловите конкретный который вы ждете
Такая запись слишком длинная и плохо читается, опять же противоречит pep8.try: req = requests.get(url) except Exception: print('Error open. __', Exception)
Можно так переписать[t.replace('\xa0', ' ') for t in doc.xpath('//span[@itemprop="price"]/text()')] or [t.replace('\xa0', ' ') for t in doc.xpath('//span[@id="mm-saleDscPrc"]/text()')]
listGoodsLinks = [] #i = 0 for path in listPages: doc = get_doc(path) listGoods = doc.xpath('//div[@id="ResultSetItems"]/table//h3/a') #i = i + 1 #if i > 1: break for elem in listGoods: href = elem.get('href') listGoodsLinks.append(href)result = [] for path in path_list: doc = get_doc(path) goods_list = doc.xpath('//div[@id="ResultSetItems"]/table//h3/a') goods_link_list = [elem.get('href') for elem in goods_list] result = chain(result, goods_link_list)
Отредактировано PanovSergey (Март 5, 2014 13:16:20)
Офлайн
857
zlodiak
всё таки получилась программа трудная для чтения
чтобы написать парсер, нужно первое, второе и третье
чтобы написать первое, нужно четвертое, пятое и шестое
чтобы написать второе, нужно седьмое, восьмое и девятое
чтобы написать третье, нужно десятое, одиннадцатое и двенадцатое
чтобы написать четвёртое, нужно ...
zlodiakdef record_xml(xml, fileName='xml.xml'): try: with open(fileName, "w") as file: file.write(xml) except Exception: print('Error record', Exception) else: print('record ok')
дано: строка с xml-кодом и имя файла для вывода
получить: строка записана в файл, файл закрыт
xml_to_file(xml, ofname)
дано: строка с xml-кодом и имя файла для вывода
утв: файл открыт
утв: строка выведена в файл
утв: файл закрыт
получить: строка записана в файл, файл закрыт
дано: строка с xml-кодом и имя файла для вывода
открыть файл
утв: файл открыт
записать строку в файл
утв: строка выведена в файл
закрыть файл
утв: файл закрыт
ничего не делать
получить: строка записана в файл, файл закрыт
Отредактировано py.user.next (Март 6, 2014 04:47:16)
Офлайн
0
спасибо большое за важную информацию. честно говоря, даже не надеялся на такие подробные ответы
вот по этому есть вопрос, если можно…
PanovSergey
Можно так переписатьlistGoodsLinks = [] #i = 0 for path in listPages: doc = get_doc(path) listGoods = doc.xpath('//div[@id="ResultSetItems"]/table//h3/a') #i = i + 1 #if i > 1: break for elem in listGoods: href = elem.get('href') listGoodsLinks.append(href)Отредактировано PanovSergey (Март 5, 2014 13:16:20)result = [] for path in path_list: doc = get_doc(path) goods_list = doc.xpath('//div[@id="ResultSetItems"]/table//h3/a') goods_link_list = [elem.get('href') for elem in goods_list] result = chain(result, goods_link_list)
for x in str(array):
array = str(array) for x in array:
Отредактировано zlodiak (Март 7, 2014 20:25:02)
Офлайн
даже таких конструкций я стараюсьа чем первый вариант не угодил? Там все в одном месте и сразу ясно, а тут надо разносить внимание на 2 строки ).
избегать: for x in str(array):
a записывать их так:
array = str(array)
for x in array:
Офлайн