Получите href из html с помощью Beautiful Soup select или lxml xpath - PullRequest
0 голосов
/ 02 июля 2019

На веб-сайте Rotten Tomatoes я занимаюсь веб-очисткой, например, здесь .

Я использую Python вместе с модулями Beautiful Soup и lxml.

Я хочу извлечь информацию о фильме, например: - Жанр: драма, музыкальное и исполнительское искусство

  • Режиссер: Кирилл Серебренников

  • Автор: Михаил Идов, Лили Идова, Иван Капитонов, Кирилл Серебренников, Наталья Науменко

  • Автор (ссылки) : / знаменитости / michael_idov, / знаменитости / lily_idova, / знаменитости / ivan_kapitonov, / знаменитости / kirill_serebrennikov, / знаменитости / natalya_naumenko

Я проверил html страницы, чтобы получить рекомендации по путям:

                    <li class="meta-row clearfix">
                        <div class="meta-label subtle">Rating: </div>
                        <div class="meta-value">NR</div>
                    </li>


                    <li class="meta-row clearfix">
                        <div class="meta-label subtle">Genre: </div>
                        <div class="meta-value">

                                <a href="/browse/opening/?genres=9">Drama</a>, 

                                <a href="/browse/opening/?genres=12">Musical &amp; Performing Arts</a>

                        </div>
                    </li>


                    <li class="meta-row clearfix">
                        <div class="meta-label subtle">Directed By: </div>
                        <div class="meta-value">

                                <a href="/celebrity/kirill_serebrennikov">Kirill Serebrennikov</a>

                        </div>
                    </li>


                    <li class="meta-row clearfix">
                        <div class="meta-label subtle">Written By: </div>
                        <div class="meta-value">

                                <a href="/celebrity/michael_idov">Mikhail Idov</a>, 

                                <a href="/celebrity/lily_idova">Lili Idova</a>, 

                                <a href="/celebrity/ivan_kapitonov">Ivan Kapitonov</a>, 

                                <a href="/celebrity/kirill_serebrennikov">Kirill Serebrennikov</a>, 

                                <a href="/celebrity/natalya_naumenko">Natalya Naumenko</a>

                        </div>
                    </li>


                    <li class="meta-row clearfix">
                        <div class="meta-label subtle">In Theaters: </div>
                        <div class="meta-value">
                            <time datetime="2019-06-06T17:00:00-07:00">Jun 7, 2019</time>
                            <span style="text-transform:capitalize">&nbsp;limited</span>
                        </div>
                    </li>




                    <li class="meta-row clearfix">
                        <div class="meta-label subtle">Runtime: </div>
                        <div class="meta-value">
                            <time datetime="P126M">
                                126 minutes
                            </time>
                        </div>
                    </li>


                    <li class="meta-row clearfix">
                    <div class="meta-label subtle">Studio: </div>
                    <div class="meta-value">

                            <a href="http://sonypictures.ru/leto/" target="movie-studio">Gunpowder &amp; Sky</a>

                    </div>

            </li>

Я создал объекты html следующим образом:

    page_response = requests.get(url, timeout=5)
    page_content = BeautifulSoup(page_response.content, "html.parser")
    tree = html.fromstring(page_response.content)

Например, для Writer, поскольку мне нужен только текст элемента, его довольно легко получить:

page_content.select('div.meta-value')[3].getText()

Или используя xpart для рейтинга:

tree.xpath('//div[@class="meta-value"]/text()')[0]

Для доступа к Writer Links, где у меня есть проблема, для доступа к html чанку я делаю это:

page_content.select('div.meta-value')[3]

Что дает:

<div class="meta-value">
<a href="/celebrity/michael_idov">Mikhail Idov</a>, 

                                <a href="/celebrity/lily_idova">Lili Idova</a>, 

                                <a href="/celebrity/ivan_kapitonov">Ivan Kapitonov</a>, 

                                <a href="/celebrity/kirill_serebrennikov">Kirill Serebrennikov</a>, 

                                <a href="/celebrity/natalya_naumenko">Natalya Naumenko</a>

Или:

tree.xpath('//div[@class="meta-value"]')[3]

Предоставление:

<Element div at 0x2915a4c54a8>

Проблема в том, что я не могу извлечь 'href'. Я хочу получить вывод:

/celebrity/michael_idov, /celebrity/lily_idova, /celebrity/ivan_kapitonov, /celebrity/kirill_serebrennikov, /celebrity/natalya_naumenko

Я пробовал:

page_content.select('div.meta-value')[3].get('href')
tree.xpath('//div[@class="meta-value"]')[3].get('href')
tree.xpath('//div[@class="meta-value"]/@href')[3]

Все с нулевым результатом или результатом ошибки. Может ли кто-нибудь помочь мне в этом?

Заранее спасибо! Ура!

1 Ответ

0 голосов
/ 03 июля 2019

Попробуйте следующие скрипты, чтобы получить интересующий вас контент. Обязательно протестируйте оба из них, используя разные фильмы. Я полагаю, они оба будут производить желаемый результат. Я старался избегать любых жестко закодированных индексов для таргетинга контента.

Использование css-селектора:

import requests
from bs4 import BeautifulSoup

r = requests.get('https://www.rottentomatoes.com/m/leto')
soup = BeautifulSoup(r.text,'lxml')

directed = soup.select_one(".meta-row:contains('Directed By') > .meta-value > a").text
written = [item.text for item in soup.select(".meta-row:contains('Written By') > .meta-value > a")]
written_links = [item.get("href") for item in soup.select(".meta-row:contains('Written By') > .meta-value > a")]
print(directed,written,written_links)

Использование xpath:

import requests
from lxml.html import fromstring

r = requests.get('https://www.rottentomatoes.com/m/leto')
root = fromstring(r.text)

directed = root.xpath("//*[contains(.,'Directed By')]/parent::*/*[@class='meta-value']/a/text()")
written = root.xpath("//*[contains(.,'Written By')]/parent::*/*[@class='meta-value']/a/text()")
written_links = root.xpath(".//*[contains(.,'Written By')]/parent::*/*[@class='meta-value']/a//@href")
print(directed,written,written_links)

В случае приведения я использовал списки, чтобы использовать .strip() для отдельного элемента для удаления пробелов. normalize-space() - идеальный вариант для этого.

cast = [item.strip() for item in root.xpath("//*[contains(@class,'cast-item')]//a/span[@title]/text()")]
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...