Я пытаюсь извлечь номер рейтинга из этой ссылки пример ссылки: рейтинг пользователя kaggle № 1. Более ясно на изображении:
Я использую следующий код:
def get_single_item_data(item_url):
sourceCode = requests.get(item_url)
plainText = sourceCode.text
soup = BeautifulSoup(plainText)
for item_name in soup.findAll('h4',{'data-bind':"text: rankingText"}):
print(item_name.string)
item_url = 'https://www.kaggle.com/titericz'
get_single_item_data(item_url)
Результат None
. Проблема в том, что soup.findAll('h4',{'data-bind':"text: rankingText"})
выводит:
[<h4 data-bind="text: rankingText"></h4>]
Но в html-ссылке при проверке это выглядит так:
<h4 data-bind="text: rankingText">1st</h4>
. Это можно увидеть на изображении:
Понятно, что текст отсутствует. Как я могу преодолеть это?
Редактировать: Распечатывая переменную soup
в терминале, я вижу, что это значение существует:
Так что должен быть способ доступа через soup
.
Изменить 2: Я безуспешно пытался использовать наиболее проголосовавший ответ из этого -content-add-from-js "> вопрос stackoverflow . Может быть решение где-то там.
4 ответа
Если вы не собираетесь пытаться автоматизировать браузер через selenium
, как предложил @Ali, вам придется проанализировать javascript, содержащий нужную информацию . Вы можете сделать это по-разному. Вот рабочий код, который находит script
с помощью шаблон регулярного выражения, затем извлекает объект profile
, загружает его с помощью json
в словарь Python и выводит желаемый рейтинг:
import re
import json
from bs4 import BeautifulSoup
import requests
response = requests.get("https://www.kaggle.com/titericz")
soup = BeautifulSoup(response.content, "html.parser")
pattern = re.compile(r"profile: ({.*}),", re.MULTILINE | re.DOTALL)
script = soup.find("script", text=pattern)
profile_text = pattern.search(script.text).group(1)
profile = json.loads(profile_text)
print profile["ranking"], profile["rankingText"]
Печать:
1 1st
Я решил вашу проблему с помощью регулярных выражений на простой текст:
def get_single_item_data(item_url):
sourceCode = requests.get(item_url)
plainText = sourceCode.text
#soup = BeautifulSoup(plainText, "html.parser")
pattern = re.compile("ranking\": [0-9]+")
name = pattern.search(plainText)
ranking = name.group().split()[1]
print(ranking)
item_url = 'https://www.kaggle.com/titericz'
get_single_item_data(item_url)
Это возвращает только номер ранга, но я думаю, что это поможет вам, так как из того, что я вижу rankText, просто добавьте 'st', 'th' и т. Д. Справа от номера
Это может из-за динамического заполнения данных.
Какой-то код JavaScript, заполните этот тег после загрузки страницы. Таким образом, если вы получаете html, используя запросы, он еще не заполнен.
<h4 data-bind="text: rankingText"></h4>
Пожалуйста, ознакомьтесь с веб-драйвером Selenium. Используя этот драйвер, вы можете получить всю страницу и запустить js как обычно.
Данные связаны с использованием javascript, как предполагает атрибут «data-bind».
Однако, если вы загружаете страницу, например, с помощью wget
, вы увидите, что значение ratingText на самом деле находится внутри этого элемента скрипта при начальной загрузке:
<script type="text/javascript"
profile: {
...
"ranking": 96,
"rankingText": "96th",
"highestRanking": 3,
"highestRankingText": "3rd",
...
Таким образом, вы могли бы использовать это вместо этого.
Похожие вопросы
Связанные вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.