Неверные данные при использовании BeautifulSoup - PullRequest
0 голосов
/ 25 июня 2018

Хочу разобрать сайт с информацией о киносеансах.Для этого я использую парсер BeautifulSoup, но он возвращает неверные данные.Например, если я вручную проверяю это непосредственно в коде page , это время будет 27-го: 23:45, 19:40.Но он возвращает неверный список ['21:00', '23:00'] и неверные данные из div:

<div class="showtimes-line has-21 has-23">
 <div class="showtimes-line-technology t-cinetech t-2d">
  <div class="showtimes-line-technology-title ">
   Cinetech+, 2D
  </div>
  <div class="showtimes-line-hours-wrapper">
   <a class="time h-21 " data-brand="Планета Кіно" data-category="2d" data-id="00000000000000000000000000000631" data-list="movie" data-name="Дедпул 2 (18+)" data-position="4" data-seat="" href="https://pay.planetakino.ua/hall/imax-kiev/484437" rel="nofollow">
    21:00
   </a>
   <a class="time h-23 " data-brand="Планета Кіно" data-category="2d" data-id="00000000000000000000000000000631" data-list="movie" data-name="Дедпул 2 (18+)" data-position="5" data-seat="" href="https://pay.planetakino.ua/hall/imax-kiev/486327" rel="nofollow">
    23:00
   </a>
  </div>
 </div>
</div>

Вот мой код:

def get_sessions(response, date):
    """Return information about sessions at `date`."""
    sessions = []
    soup = BeautifulSoup(response.text, 'lxml')
    days_div = soup.find_all('div', class_='showtimes-row')

    for div in days_div:
        day_str = div.find('span', class_='date').text
        day_int = int(day_str.split()[0])

        if int(date.day) == day_int:
            sessions_row = div.find('div', class_='showtimes-line')
            for session in sessions_row.find_all('a', class_='time'):
                sessions.append(session.text.strip())
            print(sessions) 
            print(sessions_row.prettify())

    return sessions

Запрос был сделан следующим образом:

url='https://planetakino.ua/lvov2/movies/deadpool_2/#cinetech_2d_3d_4dx_week'
response = requests.get(url)
sessions = get_sessions(response, film.period)

1 Ответ

0 голосов
/ 26 июня 2018

Я не заметил, что вы указали film.period в коде, размещенном на Github, поэтому я не стал отлаживать ваш код без этого и решил реализовать его с нуля.

После быстрогоПоиском, я узнал, что в кинотеатре «Планета Кино» есть XML-файлы на их веб-сайте с графиком показа фильмов.Вы можете найти некоторые из них здесь .Я не уверен, почему, но там не было записи для lvov2 кинотеатра с сеансами, соответствующими ссылке из вашего вопроса.Однако мне удалось найти его, просто изменив часть URL: http://planetakino.ua/lvov2/ua/showtimes/xml/.

Код ниже должен делать именно то, что вы хотите:

import datetime
from typing import List

import dateparser
import requests
from bs4 import BeautifulSoup, Tag

Date = datetime.datetime
Screening = Tag
Screenings = List[Tag]


def get_movie_id(soup: BeautifulSoup, searched_movie: str) -> int:
    movie = soup.find(
        lambda elem: elem.name == 'movie' and searched_movie in elem.title.string
    )
    movie_id = int(movie['id'])
    return movie_id


def get_movie_screenings(soup: BeautifulSoup, movie_id: int, searched_date: Date) -> Screenings:
    formatted_date = searched_date.strftime('%Y-%m-%d')
    screenings = soup.select(f'showtimes '
                             f'> day[date={formatted_date}] '
                             f'> show[movie-id={movie_id}]')
    return screenings


def get_show_times(searched_movie: str, searched_date: Date) -> Screenings:
    url = 'http://planetakino.ua/lvov2/ua/showtimes/xml/'
    html = requests.get(url).text
    soup = BeautifulSoup(html, 'xml')

    movie_id = get_movie_id(soup, searched_movie)
    screenings = get_movie_screenings(soup, movie_id, searched_date)
    return screenings


date = dateparser.parse(input('Type the date: '))
if date is not None:
    import pprint
    pprint.pprint(get_show_times('Дедпул 2', date))
else:
    print('Sorry, I cannot parse the date you gave me.')

Вывод:

Type the date: 27 червня, середа
[<show full-date="2018-06-27 19:40:00" hall-id="104" movie-id="2385" order-url="https://pay.planetakino.ua/hall/pk-lvov2/485693" technology="Cinetech+2D" theatre-id="pk-lvov2" time="19:40"/>,
 <show full-date="2018-06-27 23:45:00" hall-id="101" movie-id="2385" order-url="https://pay.planetakino.ua/hall/pk-lvov2/485506" technology="4dx" theatre-id="pk-lvov2" time="23:45"/>]

Я использовал dateparser для анализа введенной даты, поэтому он работает с различными форматами, языками, например, 27th June, 27 червня, середа и многими другими.Это действительно здорово, и мне это нравится.

Не торопитесь, чтобы прочитать и понять код, возможно, вы захотите взглянуть на .select() и CSS-селекторы ( дочерние комбинаторы и селекторы атрибутов ).

Примечание: вам нужно использовать Python 3.6+, так как я использовал Интерполяция буквенных строк (f-strings) и тип подсказки (3,5 +).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...