Python 在完全平坦的HTML层次结构上使用BeautifulSoup
所以我是一个网络垃圾爱好者,遇到了一些我从未见过的HTML格式。我需要的所有信息都在一个完全扁平的层次结构中。我需要知道日期/电影名/地点/便利设施 它的布局是这样的(就像这样):Python 在完全平坦的HTML层次结构上使用BeautifulSoup,python,html,beautifulsoup,Python,Html,Beautifulsoup,所以我是一个网络垃圾爱好者,遇到了一些我从未见过的HTML格式。我需要的所有信息都在一个完全扁平的层次结构中。我需要知道日期/电影名/地点/便利设施 它的布局是这样的(就像这样): 7月1日 精英 “地点:千禧公园” “设施:请做一场排球比赛…” 菲利普斯船长 “地点:蒙哥马利沃德公园” 7月2日 神奇的狐狸先生 我希望最终在字典或列表中使用csvwriter或Dictwriter将其作为CSV文件写入;所以输出像 [7月1日,千年公园托普肯特,“请做一场排球比赛……”, [
7月1日
精英
“地点:千禧公园”
“设施:请做一场排球比赛…”
菲利普斯船长
“地点:蒙哥马利沃德公园”
7月2日
神奇的狐狸先生
我希望最终在字典或列表中使用csvwriter或Dictwriter将其作为CSV文件写入;所以输出像
[7月1日,千年公园托普肯特,“请做一场排球比赛……”,
[7月1日,菲利普船长,蒙哥马利沃德公园,]等
正如您所看到的,令人烦恼的是,当两部电影在同一日期放映时,日期只显示在第一部电影之前;在下一个日期之前列出的所有电影都属于该初始日期
伙计们?如何使多部电影落在上面标签中指定的日期之下?可能认为查找下一个兄弟姐妹,包括检查标记是否为
标记 这是一个非常难看的解决方案,在使用之前应该使其更加健壮,但类似的方法应该有效:
from bs4 import BeautifulSoup
import re
import csv
doc = """<div class="caption">
<strong>July 1</strong>
<br>
<em>Top Gun</em>
<br>
"Location: Millennium Park"
<br>
"Amenities: Please be a volleyball tournament..."
<br>
<em>Captain Phillips</em>
<br>
"Location: Montgomery Ward Park"
<br>
<br>
<strong>July 2</strong>
<br>
<em>The Fantastic Mr. Fox </em>
<br>
"Location: Somewhere"
<br>
"Amenities: Something something"
<br>"""
soup = BeautifulSoup(doc.replace("<br>", "<br/>"))
data = []
for date in soup.find_all("strong"):
sibling = date.next_sibling
while sibling and sibling.name != "strong":
if sibling.name == "em":
title = sibling
location = title.find_next("br").next
extra = location.find_next("br").next
row = []
row.append(date.text)
row.append(title.text)
row.append(re.findall('(?<=:)[^"]*', location)[0])
extra_val = re.findall('(?<=:)[^"]*', extra)
if len(extra_val):
row.append(extra_val[0])
data.append(row)
sibling = sibling.next_sibling
with open('foo.csv', 'wb') as csvfile:
writer = csv.writer(csvfile)
writer.writerows(data)
在这个HTML中,em
是p
的子元素。现在让我们看看BeautifulSoup如何解析一些HTML:
>>> from bs4 import BeautifulSoup
>>> BeautifulSoup('<br><p>Hello<br></p>', 'html.parser')
<br><p>Hello<br/></p></br>
>>> BeautifulSoup('<br><p>Hello<br></p>', 'html5lib')
<html><head></head><body><br/><p>Hello<br/></p></body></html>
>>来自bs4导入组
>>>BeautifulSoup(“
你好,
”,“html.parser”)
你好
>>>BeautifulSoup(“
你好,
”,“html5lib”)
你好
html.parser
是Pythons内置的html解析器,默认情况下就是它。如您所见,它添加了一个结束标记,并将一个结束标记转换为结束标记。简言之,如果没有关闭标记,它就不能很好地完成工作。这就搞乱了什么元素应该是兄弟
另一方面,
html5lib
尝试匹配浏览器的功能,并使用它而不是doc。替换(“
”,“
”)也可以工作。但是,它的速度要慢得多,而且它没有Python或BeautifulSoup,因此需要另一个pip安装html5lib
才能工作。Hey@Erik Vesteraas,并不真正理解doc.replace的用途。你能详细说明一下吗?谢谢
<p></p><em></em>
<p><em></em></p>
>>> from bs4 import BeautifulSoup
>>> BeautifulSoup('<br><p>Hello<br></p>', 'html.parser')
<br><p>Hello<br/></p></br>
>>> BeautifulSoup('<br><p>Hello<br></p>', 'html5lib')
<html><head></head><body><br/><p>Hello<br/></p></body></html>