为啥 BeautifulSoup 将 <html><body><p> 添加到我的结果中?
Posted
技术标签:
【中文标题】为啥 BeautifulSoup 将 <html><body><p> 添加到我的结果中?【英文标题】:Why BeautifulSoup add <html><body><p> to my results?为什么 BeautifulSoup 将 <html><body><p> 添加到我的结果中? 【发布时间】:2018-07-08 14:26:52 【问题描述】:问题
我有以下Page01.htm
<!DOCTYPE html><html lang="it-IT"><head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=Edge"> <head><title>Title here</title></head>
<body>
<script id="TargetID" type="application/json"><![CDATA[
"name":"Kate", "age":22, "city":"Boston"
]]>
</script><script id=“AnotherID” type="application/json"><![CDATA[ "name":"John", "age":31, "city":"New York"]]>
</script>
</body></html>
我想用ID=TargetID
提取脚本标签之间的JSON 中的信息。
我做了什么
我编写了以下 Python 3.6 代码:
from bs4 import BeautifulSoup
import codecs
page_path="/Users/me/Page01.htm"
page = codecs.open(page_path, "r", "utf-8")
soup = BeautifulSoup(page.read(), "lxml")
vegas = soup.find_all(id="TargetID")
invalid_tags = ['script']
soup = BeautifulSoup(str(vegas),"lxml")
for tag in invalid_tags:
for match in soup.findAll(tag):
match.replaceWithChildren()
JsonZ = str(soup)
现在,如果我查看 vegas
变量内部,我可以看到
[<script id="TargetID" type="application/json"><![CDATA[
> "name":"Kate", "age":22, "city":"Boston" ]]> </script>]
但如果我尝试删除脚本标签(使用this answer 脚本),我会得到以下JsonZ
变量
'<html><body><p>[<![CDATA[\n "name":"Kate", "age":22, "city":"Boston"\n]]>\n]</p></body></html>'
没有脚本标签但有另外 3 个标签 (<html><body><p>
) 完全没用。
我的目标是让以下字符串 "name":"Kate", "age":22, "city":"Boston"
与 Python JSON 模块一起加载。
【问题讨论】:
【参考方案1】:它可以变得更简单:
from bs4 import BeautifulSoup
soup = BeautifulSoup(open("/Users/me/Page01.htm", encoding='utf-8'), "html.parser")
result = soup.find('script', type='application/json', id='TargetID').text
# Workaround to get CDATA content (It seems that it can't be done with bs):
result = result.replace("<![CDATA[", "").replace("]]>", "").strip()
【讨论】:
谢谢,它工作得很好,它是一个非常好的代码!我将@Bill Bell 的答案标记为“acceprance”,只是因为对 BeautifulSoup 为什么添加上面列出的三个标签进行了解释。再次感谢您。【参考方案2】:BeautifulSoup 几乎可以接受任何给它的东西,并尝试将其转换为完整的 HTML 页面。这就是您收到'<html><body> ...'
的原因。通常这是一件好事,因为 HTML 的格式可能很糟糕,但 BeautifulSoup 仍会处理它。
在您的情况下,提取该 json 的一种方法是这样的。
>>> import bs4
>>> page = bs4.BeautifulSoup(open('Page01.htm').read(), 'lxml')
>>> first_script = page.select('#TargetID')[0].text
>>> first_script
'<![CDATA[\n "name":"Kate", "age":22, "city":"Boston"\n]]>\n'
>>> content = first_script[first_script.find(''): 1+first_script.rfind('')]
>>> content
' "name":"Kate", "age":22, "city":"Boston"'
一旦你有了这个,你就可以把它变成一个 Python 字典,就像这样。
>>> import json
>>> d = json.loads(content)
>>> d['name']
'Kate'
>>> d['age']
22
>>> d['city']
'Boston'
【讨论】:
以上是关于为啥 BeautifulSoup 将 <html><body><p> 添加到我的结果中?的主要内容,如果未能解决你的问题,请参考以下文章
为啥 BeautifulSoup 与“从未检索到任务异常”相关?
python/beautifulsoup 查找所有带有特定锚文本的 <a href>