使用BeautifulSoup的数据不正确

时间:2018-06-25 17:17:00

标签: python parsing beautifulsoup

我想用有关电影会议的信息来分析网站。为此,我使用解析器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 :(得分:4)

我还没有注意到您在Github上托管的代码中提供了film.period,因此我不费吹灰之力调试您的代码,并决定从头开始实施。

快速搜索后,我发现Planeta Kino电影院的网站上有XML文件,其中包含电影的放映时间。您可以找到其中的一些here。我不确定为什么,但是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 June27 червня, середа等。真的很棒,我喜欢它。

花些时间阅读和理解代码,您可能想看看.select()CSS selectorschild combinatorattribute selectors)。

注意:由于我使用了Literal String Interpolationf-strings)和类型提示(3.5+),因此您需要使用Python 3.6 +。