Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/html/86.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 在完全平坦的HTML层次结构上使用BeautifulSoup_Python_Html_Beautifulsoup - Fatal编程技术网

Python 在完全平坦的HTML层次结构上使用BeautifulSoup

Python 在完全平坦的HTML层次结构上使用BeautifulSoup,python,html,beautifulsoup,Python,Html,Beautifulsoup,所以我是一个网络垃圾爱好者,遇到了一些我从未见过的HTML格式。我需要的所有信息都在一个完全扁平的层次结构中。我需要知道日期/电影名/地点/便利设施 它的布局是这样的(就像这样): 7月1日 精英 “地点:千禧公园” “设施:请做一场排球比赛…” 菲利普斯船长 “地点:蒙哥马利沃德公园” 7月2日 神奇的狐狸先生 我希望最终在字典或列表中使用csvwriter或Dictwriter将其作为CSV文件写入;所以输出像 [7月1日,千年公园托普肯特,“请做一场排球比赛……”, [

所以我是一个网络垃圾爱好者,遇到了一些我从未见过的HTML格式。我需要的所有信息都在一个完全扁平的层次结构中。我需要知道日期/电影名/地点/便利设施

它的布局是这样的(就像这样):


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>