Форум сайта python.su
0
Появилась нужда разобраться страничку сайта http://tourdom.tv/happy-hour/schastlivyj-chas/.
Всегда в таких задачах использовал библиотеку lxml.html и при помощи css select указывал какие нужно данные получить.
На данной странице такой вариант на сколько я вижу не пройдёт, страница сверстана так, что нет четкой структуры вложенности и нужные теги не имеют идентификатора уникального и не принадлежат ни к какому определённому классу. Из-за этого я не знаю как распарсить эту страницу. Помогите пожалуйста советом, как это можно сделать. Если я чего не знаю о lxml.html тыкните носом пожалуйста.
Офлайн
857
d54wvzc+i5zirs
Если я чего не знаю о lxml.html
Офлайн
0
py.user.next
Раз на ваш взгляд все элементарно, покажите как вы на пример извлечёте даты только на турпакеты?
Офлайн
1
Офлайн
26
Как вариант, загрузил содержимое страницы, отрезал ненужное, передал дальше в lxml.
Отредактировано ajib6ept (Июль 6, 2014 13:21:27)
Офлайн
7
Воспользуйтесь XPath (пример кода здесь).
Путь до таблиц (<table>) турпакетов:
//*[contains(@class, 'entry-content')]/table[position() mod 2 = 0]
//*[contains(@class, 'entry-content')]/table[position() mod 2 = 0]//td[@class='width_first_td_from_table']/b
//*[contains(@class, 'entry-content')]/table[contains(., 'БИЛЕТЫ')]/preceding::table[not(contains(., 'ТУРПАКЕТЫ')) and not(@class)]
//*[contains(@class, 'entry-content')]/table[contains(., 'БИЛЕТЫ')]/preceding::table[not(contains(., 'ТУРПАКЕТЫ')) and not(@class)]//td[@class='width_first_td_from_table']/b
Отредактировано john123 (Июль 6, 2014 21:26:52)
Офлайн
857
#!/usr/bin/env python3 import lxml.html def parse_tables(tables): sect1, sect2, sect3 = [], [], [] state = 'before' for t in tables: if state == 'before': if search_section_type(t) == 'ТУРПАКЕТЫ': state = 'section1' elif state == 'section1': if search_section_type(t) == 'БИЛЕТЫ': state = 'section2' elif is_valid_table1(t): sect1.append(get_data_table1(t)) elif is_valid_table2(t): sect1.append(get_data_table2(t)) elif state == 'section2': if search_section_type(t) == 'ОТЕЛИ': state = 'section3' elif is_valid_table1(t): sect2.append(get_data_table1(t)) elif is_valid_table2(t): sect2.append(get_data_table2(t)) elif state == 'section3': if is_valid_table1(t): sect3.append(get_data_table1(t)) elif is_valid_table2(t): sect3.append(get_data_table2(t)) return sect1, sect2, sect3 def search_section_type(t): lst = t.xpath('.//td[@class = "type_of_package"]/text()') if lst: return lst[0] def is_valid_table1(t): return 'style' in t.attrib def is_valid_table2(t): return ('class' in t.attrib and 'hide_sc_info_table' in t.attrib.get('class', '')) def get_data_table1(t): out = ( t.xpath('.//b[@class]/text()')[0], t.xpath('.//strong/text()')[0], ) out = tuple(map(str.strip, out)) return out def get_data_table2(t): out = ( t.xpath('.//tr/td[2]/text()')[0], ) out = tuple(map(str.strip, out)) return out url = 'http://tourdom.tv/happy-hour/schastlivyj-chas/' #doc = lxml.html.parse(url) doc = lxml.html.parse('file.html') #print(doc) alltables = doc.xpath('//table') #print(alltables) sect1, sect2, sect3 = parse_tables(alltables) print(sect1) print(len(sect1)) print(sect2) print(len(sect2)) print(sect3) print(len(sect3))
[('На 11.07.2014', 'Болгария, Солнечный берег,'), ('Туи',), ('На 18.07.2014', 'Кипр, Протарас,'), ('Лабиринт',), ('На 12.07.2014', 'Греция, о.Родос,'), ('Тройка',), ('На 08.07.2014', 'Испания, Коста-Брава,'), ('Лабиринт',), ('На 12.07.2014', 'Италия, о.Сардиния,'), ('Пак груп',), ('На 10.07.2014', 'Чехия, Прага,'), ('Туи',), ('На 08.07.2014', 'Турция, Алания,'), ('Санмар',), ('На 22.07.2014', 'Египет, Шарм-Эль-Шейх,'), ('Brisco',), ('На 18.07.2014', 'Хорватия, Цавтат,'), ('ПАКС',), ('На 16.07.2014', 'Черногория, Шушань,'), ('Библио Глобус',), ('На 27.07.2014', 'Тунис, Набель,'), ('Библио Глобус',)]
22
[('На 11.09.2014', 'Москва – Лондон – Москва,'), ('Москва, а/п Домодедово',), ('На 07.07.2014', 'Москва – Карловы Вары – Москва,'), ('Москва, а/п Шереметьево',)]
4
[('На 11.09.2014', 'Великобритания, Лондон,'), ('',)]
2
[guest@localhost xptours]$d54wvzc+i5zirs
покажите как вы на пример извлечёте даты только на турпакеты?
john123Не, выдаёт не всё.
Правильные только для турпакетов вот:
#!/usr/bin/env python3 import lxml.html url = 'http://tourdom.tv/happy-hour/schastlivyj-chas/' #doc = lxml.html.parse(url) doc = lxml.html.parse('file.html') #print(doc) tables = doc.xpath("//*[contains(@class, 'entry-content')]/table[contains(., 'БИЛЕТЫ')]/preceding::table[not(contains(., 'ТУРПАКЕТЫ')) and not(@class)]") print(tables, len(tables)) dates = doc.xpath("//*[contains(@class, 'entry-content')]/table[contains(., 'БИЛЕТЫ')]/preceding::table[not(contains(., 'ТУРПАКЕТЫ')) and not(@class)]//td[@class='width_first_td_from_table']/b") print(dates, len(dates))
[guest@localhost xptours]$ ./xptours_inc.py
[<Element table at 0xb721eb9c>, <Element table at 0xb721ebcc>, <Element table at 0xb721ebfc>, <Element table at 0xb721ec2c>, <Element table at 0xb721ec5c>, <Element table at 0xb721ec8c>, <Element table at 0xb721ecbc>, <Element table at 0xb721ecec>, <Element table at 0xb721ed1c>, <Element table at 0xb721ed4c>] 10
[] 0
[guest@localhost xptours]$
Отредактировано py.user.next (Июль 7, 2014 11:05:09)
Офлайн
7
Странный сайт. При перезагрузке страницы меняется верстка.
Попробуйте вот такой XPath:
//*[contains(@class, 'entry-content')]/table[contains(., 'БИЛЕТЫ')]/preceding::table[contains(@style, 'border-top')]
#!/usr/bin/env python # encoding: utf-8 import lxml.html url = 'http://tourdom.tv/happy-hour/schastlivyj-chas/' doc = lxml.html.parse(url) tables = doc.xpath(u"//*[contains(@class, 'entry-content')]/table[contains(., 'БИЛЕТЫ')]/preceding::table[contains(@style, 'border-top')]") for item in tables: date = item.xpath(".//b[@class]/text()")[0] title = item.xpath(".//strong/text()")[0].strip() price = item.xpath(".//span[@class='title_pacag']/text()")[0] print date, title, price
Отредактировано john123 (Июль 7, 2014 10:51:41)
Офлайн