Python:Getting 来自 html 的文本使用 Beautifulsoup
Python:Getting text from html using Beautifulsoup
我正在尝试从此 link link example: kaggle user ranking no1 中提取排名文本编号。图片更清晰:
我正在使用以下代码:
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>]
但是在 link 的 html 中检查时就像这样:
<h4 data-bind="text: rankingText">1st</h4>
。如图所示:
很明显,文字不见了。我怎样才能通过它?
编辑:
在终端中打印 soup
变量,我可以看到这个值存在:
所以应该有一种方法可以通过soup
访问。
编辑 2:我尝试使用这个 Whosebug question 中投票最多的答案,但没有成功。可能是附近的解决方案。
这可能是因为动态数据填充。
一些javascript代码,页面加载后填写此标签。因此,如果您使用请求获取 html,它还没有被填充。
<h4 data-bind="text: rankingText"></h4>
请看Selenium web driver。使用此驱动程序,您可以正常获取完整页面和 运行 js。
数据使用 javascript 进行数据绑定,正如 "data-bind" 属性所建议的那样。
但是,如果您使用例如wget
,您会看到 rankingText 值实际上在初始加载时位于此脚本元素内:
<script type="text/javascript"
profile: {
...
"ranking": 96,
"rankingText": "96th",
"highestRanking": 3,
"highestRankingText": "3rd",
...
所以你可以改用它。
如果您不打算按照@Ali 的建议通过selenium
尝试浏览器自动化,您将不得不解析包含所需信息的javascript.您可以通过不同的方式执行此操作。这是一个工作代码,它通过 regular expression pattern, then extracts the profile
object, loads it with json
将 script
定位到 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)
这个return只是排名数字,但我认为它会对你有所帮助,因为从我看到的rankText来看,只需在右侧添加'st'、'th'等人数
我正在尝试从此 link link example: kaggle user ranking no1 中提取排名文本编号。图片更清晰:
我正在使用以下代码:
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>]
但是在 link 的 html 中检查时就像这样:
<h4 data-bind="text: rankingText">1st</h4>
。如图所示:
很明显,文字不见了。我怎样才能通过它?
编辑:
在终端中打印 soup
变量,我可以看到这个值存在:
所以应该有一种方法可以通过soup
访问。
编辑 2:我尝试使用这个 Whosebug question 中投票最多的答案,但没有成功。可能是附近的解决方案。
这可能是因为动态数据填充。
一些javascript代码,页面加载后填写此标签。因此,如果您使用请求获取 html,它还没有被填充。
<h4 data-bind="text: rankingText"></h4>
请看Selenium web driver。使用此驱动程序,您可以正常获取完整页面和 运行 js。
数据使用 javascript 进行数据绑定,正如 "data-bind" 属性所建议的那样。
但是,如果您使用例如wget
,您会看到 rankingText 值实际上在初始加载时位于此脚本元素内:
<script type="text/javascript"
profile: {
...
"ranking": 96,
"rankingText": "96th",
"highestRanking": 3,
"highestRankingText": "3rd",
...
所以你可以改用它。
如果您不打算按照@Ali 的建议通过selenium
尝试浏览器自动化,您将不得不解析包含所需信息的javascript.您可以通过不同的方式执行此操作。这是一个工作代码,它通过 regular expression pattern, then extracts the profile
object, loads it with json
将 script
定位到 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)
这个return只是排名数字,但我认为它会对你有所帮助,因为从我看到的rankText来看,只需在右侧添加'st'、'th'等人数