Форум сайта python.su
0
Имеется такой текст
<div class="b-content-item__title"> <a href="http://pogoda.yandex.ru/nalchik/"class="b-link">Погода</a> <a href="http://pogoda.yandex.ru/nalchik/"title="облачно"class="b-weather__icon_link"> <i class="b-inline b-weather__icon b-weather__icon_ovc"></i> </a> <a href="http://pogoda.yandex.ru/nalchik/"class="b-link_black_novisit">+11 °С</a> </div> <div class="b-weather__info"> <a href="http://pogoda.yandex.ru/nalchik/"class="b-link_black_novisit">ночью +9</a> <a href="http://pogoda.yandex.ru/nalchik/"class="b-link_black_novisit">утром +7</a> </div>
import urllib2, re, time class Weather(object): def __init__(self): self.__weather__ = [] self.__rgst__ = urllib2.Request('http://www.yandex.ru/') self.__page__ = urllib2.urlopen(self.__rgst__) self.__read__ = self.__page__.read() self.__page__.close() self.__main__ = re.findall(r'<div class=["|\']b-content-item__title["|\']>(.*?)</div>', self.__read__) self.__sts__ = re.findall(r'title=["|\'](.*?)["|\']', self.__main__[0]) self.__now__ = re.findall(r'<a href=["|\'].*?["|\'].*class=["|\']b-link_black_novisit["|\']>(.*?)</a>', self.__main__[0]) self.__weather__.append(self.__sts__[0].decode('utf-8')) self.__weather__.append(self.__now__[0].decode('utf-8')) self.__main__ = re.findall(r'<div class=["|\']b-weather__info["|\']>(.*?)</div>', self.__read__) for data in re.findall(r'<a href=["|\'].*?["|\'].*?class=["|\']b-link_black_novisit["|\']>(.*?)</a>', self.__main__[0]): self.__weather__.append(data.replace(' ', ' ').decode('utf-8')) def get(self): return self.__weather__ weather = Weather() for i in weather.get(): print(i) time.sleep(5)
Офлайн
253
Viktor1703Проще как у страуса, потратить день на то чтобы изучить lxml а потом за 2 минуты долететь. Регулярки дают более быстродействующий код (обычно) и проще изучаются, но не всегда удобны.
как проще
print re.search(ur'([ \+\-]*\d+) °С',s).group(1) print re.search(ur'ночью ([ \+\-]*\d+)',s).group(1) print re.search(ur'утром ([ \+\-]*\d+)',s).group(1) >>> 11 9 7
Отредактировано doza_and (Апрель 10, 2013 21:59:05)
Офлайн
0
doza_and, Вы думаете что через lxml будет удобнее? по мне так регулярки самое то… Попробуйте посмотреть исходный код главной страницы yandex, он не структурирован а написан в одну строчу.
Отредактировано Viktor1703 (Апрель 10, 2013 21:36:52)
Офлайн
253
Если страницы разнообразные и сложные или есть повышенные требования к надежности парсинга то однозначно lxml. А тут можно даже и упростить.
Я для себя решил так - регулярки меньше 80 символов тогда регулярки если больше то парсеры
lxml если чтото специфическое то coco или pyparsing (тут выбор от требований переносить на другие языки).
Что касается советов то тут класс избыточен, достаточно функции возвращающей словарь. Ведь вам не нужны промежуточные результаты после завершения парсинга?
def get_yandex_weather(): return [{"ночью":t_n,"днем":t_d,...},{},...]
Отредактировано doza_and (Апрель 10, 2013 21:45:19)
Офлайн
0
doza_and, понял Вас, постараюсь разобраться с lxml, попробую разные варианты, благодарю за советы.
P.S. Не заметил что Вы добавили пример кода в первом Вашем сообщении, он как раз кстати, не знал о такой конструкции, думаю он мне подайдёт 
Отредактировано Viktor1703 (Апрель 10, 2013 22:47:01)
Офлайн
0
Может пригодится кому, у меня получилось так:
# -*- coding: cp1251 -*- import urllib2, re, time def Weather(): result = {1 : 'Unknown', 2 : 'Unknown', 3 : 'Unknown', 4 : 'Unknown', 5 : 'Unknown'} try: page = urllib2.urlopen(urllib2.Request('http://www.yandex.ru/')) read = page.read() try: this = re.search(r'<div class="b-content-item__title">.*?<a href="http://pogoda.yandex.ru/(.*?)[/]".*?title="(.*?)".*?>.*?</a>.*?<a.*?>(.*?)</a>.*?</div>', read) if (this and (len(this.groups()) == 3)): result[1] = this.group(1).decode('utf-8') result[2] = this.group(2).decode('utf-8') result[3] = this.group(3).decode('utf-8') finally: del this try: time = re.search(r'<div class="b-weather__info">.*?<a.*?>(.*?)</a>.*?<a.*?>(.*?)</a>.*?</div>', read) if (time and (len(time.groups()) == 2)): result[4] = time.group(1).replace(' ', ' ').decode('utf-8') result[5] = time.group(2).replace(' ', ' ').decode('utf-8') finally: del time finally: page.close() return result we = Weather() print(we[1]) # город print(we[2]) # статус погоды print(we[3]) # температура сейчас print(we[4]) # температура через несколько часов print(we[5]) # температура через пол дня #for i in we: # print(we[i]) time.sleep(60)
print re.search(ur'([ \+\-]*\d+) °С',s).group(1) print re.search(ur'ночью ([ \+\-]*\d+)',s).group(1) print re.search(ur'утром ([ \+\-]*\d+)',s).group(1)
Отредактировано Viktor1703 (Апрель 11, 2013 00:50:12)
Офлайн
857
>>> import lxml.html >>> >>> s = """ ... <div class="b-content-item__title"> ... <a href="http://pogoda.yandex.ru/nalchik/"class="b-link">Погода</a> ... <a href="http://pogoda.yandex.ru/nalchik/"title="облачно"class="b-weather__icon_link"> ... <i class="b-inline b-weather__icon b-weather__icon_ovc"></i> ... </a> ... <a href="http://pogoda.yandex.ru/nalchik/"class="b-link_black_novisit">+11 °С</a> ... </div> ... <div class="b-weather__info"> ... <a href="http://pogoda.yandex.ru/nalchik/"class="b-link_black_novisit">ночью +9</a> ... <a href="http://pogoda.yandex.ru/nalchik/"class="b-link_black_novisit">утром +7</a> ... </div> ... """ >>> >>> html = lxml.html.fromstring(s) >>> tup = html[0][2].text, html[1][0].text, html[1][1].text >>> print(tup) ('+11 °С', 'ночью\xa0+9', 'утром\xa0+7') >>> print(*tup, sep=':') +11 °С:ночью +9:утром +7 >>>
Офлайн
0
py.user.next, не плохо, только я получаю не этот кусочек кода, а весь код страницы, в ней всё в одну строку, для примера:
<html><head></head><script></script><body><div></div></body></html>
<div class="b-content-item__title"> </div>
Отредактировано Viktor1703 (Апрель 11, 2013 09:05:56)
Офлайн
857
Viktor1703lxml не опирается на то, одна там строка или много строк, она проводит синтаксический анализ языка html, используя его грамматику (браузер точно так же делает)
только я получаю не этот кусочек кода, а весь код страницы, в ней всё в одну строку
Viktor1703а вот регулярные выражения работают просто с текстом, поэтому они не отличают теги от нетегов
хотя, можно с помощью регулярки извлечь нужный мне кусок кода
<div class="b-content-item__title">
alert('<div class="b-content-item__title">');
Viktor1703эти теги div легко найти; обычно ищешь родительские теги, которые содержат нужные, а потом берёшь их дочерние элементы
мне трудно будет просто найти уровень вложенности
Отредактировано py.user.next (Апрель 11, 2013 11:24:22)
Офлайн
253
# -*- coding: cp1251 -*- import urllib2, re, time def Weather(): # result = {1 : 'Unknown', 2 : 'Unknown', 3 : 'Unknown', 4 : 'Unknown', 5 : 'Unknown'} -> result = {} try: page = urllib2.urlopen(urllib2.Request('http://www.yandex.ru/')) read = page.read() try: this = re.search(r'<div class="b-content-item__title">.*?<a href="http://pogoda.yandex.ru/(.*?)[/]".*?title="(.*?)".*?>.*?</a>.*?<a.*?>(.*?)</a>.*?</div>', read) -> спорный вопрос - но можно множество проверок убрать и просто ловить Эксепшены. if (this and (len(this.groups()) == 3)): result[1] = this.group(1).decode('utf-8') result[2] = this.group(2).decode('utf-8') result[3] = this.group(3).decode('utf-8') finally: del this -> работает сборщик мусора del не обязателен а иногда и вреден try: time = re.search(r'<div class="b-weather__info">.*?<a.*?>(.*?)</a>.*?<a.*?>(.*?)</a>.*?</div>', read) if (time and (len(time.groups()) == 2)): result[4] = time.group(1).replace(' ', ' ').decode('utf-8') result[5] = time.group(2).replace(' ', ' ').decode('utf-8') finally: del time finally: page.close() return result we = Weather() -> вместо кучи принтов пойдет pprint we print(we[1]) # город print(we[2]) # статус погоды print(we[3]) # температура сейчас print(we[4]) # температура через несколько часов print(we[5]) # температура через пол дня #for i in we: # print(we[i]) time.sleep(60)-> это так понимаю для вижуала в c++ можно жать не f5 а чтото типа ctrl f5 или shift точно не помню - и консоль не закроется.
Отредактировано doza_and (Апрель 11, 2013 18:47:58)
Офлайн