Beautiful Soup find () не находит всех результатов для Class - PullRequest
1 голос
/ 06 октября 2019

У меня есть код, пытающийся извлечь все html-содержимое из контейнера треклистов, в котором должно быть 88 песен. Информация определенно есть (я напечатал суп, чтобы проверить), поэтому я не уверен, почему все после первых 30 react-contextmenu-wrapper потеряно.

from bs4 import BeautifulSoup
from urllib.request import urlopen
import re


spotify = 'https://open.spotify.com/playlist/3vSFv2hZICtgyBYYK6zqrP'
html = urlopen(spotify)
soup = BeautifulSoup(html, "html5lib")

main = soup.find(class_ = 'tracklist-container')
print(main)

Спасибо за помощь. Текущие выходные данные печати:

                  1.
              </div></div><div class="tracklist-col name"><div class="top-align track-name-wrapper"><span class="track-name" dir="auto">Move On - Teen Daze Remix</span><span class="artists-albums"><a href="/artist/3HrczLBDJXJu6dJWEMbKHa" tabindex="-1"><span dir="auto">Garden City Movement</span></a>     • <a href="/album/4p8FxnuYzykCcN7xbjA9jq" tabindex="-1"><span dir="auto">Entertainment</span></a></span></div></div><div class="tracklist-col explicit"></div><div class="tracklist-col duration"><div class="top-align"><span class="total-duration">5:11</span><span class="preview-duration">0:30</span></div></div><div class="progress-bar-outer"><div class="progress-bar"></div></div></li><li class="tracklist-row js-track-row tracklist-row--track track-has-preview" data-position="2" role="button" tabindex="0"><div class="tracklist-col position-outer"><div class="play-pause top-align"><svg aria-label="Play" class="svg-play" role="button"><use xlink:href="#icon-play" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg><svg aria-label="Pause" class="svg-pause" role="button"><use xlink:href="#icon-pause" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg></div><div class="tracklist-col__track-number position top-align">
                  2.
              </div></div><div class="tracklist-col name"><div class="top-align track-name-wrapper"><span class="track-name" dir="auto">Flicker</span><span class="artists-albums"><a href="/artist/4qpWUfUAeI34HzvCORn1ze" tabindex="-1"><span dir="auto">Forhill</span></a>     • <a href="/album/0gfz1Tbst40swwL357cRqG" tabindex="-1"><span dir="auto">Flicker</span></a></span></div></div><div class="tracklist-col explicit"></div><div class="tracklist-col duration"><div class="top-align"><span class="total-duration">3:45</span><span class="preview-duration">0:30</span></div></div><div class="progress-bar-outer"><div class="progress-bar"></div></div></li><li class="tracklist-row js-track-row tracklist-row--track track-has-preview" data-position="3" role="button" tabindex="0"><div class="tracklist-col position-outer"><div class="play-pause top-align"><svg aria-label="Play" class="svg-play" role="button"><use xlink:href="#icon-play" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg><svg aria-label="Pause" class="svg-pause" role="button"><use xlink:href="#icon-pause" xmlns:xlink="http://www.w3.org/1999/xlink"></use></svg></div><div class="tracklist-col__track-number position top-align">

...

                  30.
              </div></div><div class="tracklist-col name"><div class="top-align track-name-wrapper"><span class="track-name" dir="auto">Trapdoor</span><span class="artists-albums"><a href="/artist/3nqTFzjmi1LLM6pn0TRMv8" tabindex="-1"><span dir="auto">Eagle Eyed Tiger</span></a>     • <a href="/album/48Q8Jgk1x4wiHWecV4nlz6" tabindex="-1"><span dir="auto">Future or Past</span></a></span></div></div><div class="tracklist-col explicit"></div><div class="tracklist-col duration"><div class="top-align"><span class="total-duration">4:14</span><span class="preview-duration">0:30</span></div></div><div class="progress-bar-outer"><div class="progress-bar"></div></div></li></ol><button class="link js-action-button" data-track-type="view-all-button">View all on Spotify</button></div>

Последняя запись должна быть 88-й. Такое ощущение, что мои результаты поиска были усечены.

Ответы [ 3 ]

1 голос
/ 06 октября 2019

Поскольку казалось, что вы на правильном пути, я не пытался полностью решить проблему, а пытался дать вам подсказку, которая может быть полезна: Выполнить динамическое создание веб-страниц .

" Почему Selenium? Не достаточно ли Beautiful Soup?

Для просмотра веб-страниц с помощью Python часто требуется всего лишь использование Beautiful Soup для достижения цели. Beautiful Soup - очень мощная библиотекаэто делает очистку веб-страниц за счет обхода DOM (объектной модели документа) проще, но она выполняет только статическую очистку. Статическая очистка игнорирует JavaScript. Она извлекает веб-страницы с сервера без помощи браузера. Вы получаете именно то, что видите в«Просмотреть источник страницы», а затем нарезать его и нарезать кубиками. Если искомые данные доступны только в «просмотре источника страницы», вам не нужно идти дальше. Но если вам нужны данные, которые присутствуют вкомпоненты, которые отображаются при нажатии на ссылки JavaScript, на помощь приходит динамическая очистка. Utiful Soup и Selenium позаботятся о динамическом очищении. Selenium автоматизирует взаимодействие с браузером из python. Следовательно, данные, представленные ссылками JavaScript, можно сделать доступными путем автоматизации нажатий кнопок с помощью Selenium, а затем извлечь их с помощью Beautiful Soup. "https://medium.com/ymedialabs-innovation/web-scraping-using-beautiful-soup-and-selenium-for-dynamic-page-2f8ad15efe25

Вот что я вижу в конце 30 песен вDOM, который ссылается на кнопку:

    </li>
   </ol>
   <button class="link js-action-button" data-track-type="view-all-button">
    View all on Spotify
   </button>
  </div>
0 голосов
/ 06 октября 2019

Все это есть в ответе только внутри тега script .

Вы можете увидеть начало соответствующего объекта javascript здесь:

enter image description here

Я бы выстроил необходимую строку и проанализировал с помощью jsonбиблиотека.


Py:

import requests, re, json

r = s.get('https://open.spotify.com/playlist/3vSFv2hZICtgyBYYK6zqrP')
p = re.compile(r'Spotify\.Entity = (.*?);')
data = json.loads(p.findall(r.text)[0])
print(len(data['tracks']['items']))
0 голосов
/ 06 октября 2019

Это потому, что вы делаете

main = soup.find(class_ = 'tracklist-container')

класс "tracklist-container" содержит только эти 30 элементов, я не уверен, что вы пытаетесь достичь, но если вы хотите, что потомпопробуйте потом разобрать класс.

другими словами, класс содержит 30 песен, я зашел на сайт и нашел 30 песен, так что это может быть только для зарегистрированных пользователей.

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