Python和BeautifulSoup - 使用<dt>和</dt> <dd>标记

时间:2016-06-03 20:35:28

标签: python beautifulsoup

我试图使用python3和beautifulsoup4从在线学校列表中提取数据。以下是数据变量的定义方式:

soup = BeautifulSoup(r.content, "html.parser")
g_data = soup.find_all("div", {"class": "school_data"})

以下是g_data []中每个列表元素的结构:

<div class="school_data">
    <h4 class="cyan_header">Coop Tech<br/></h4>
    <dl>
        <dt>School Type: </dt>
        <dd>Academic</dd>
        <dt>Another Heading: </dt>
        <dd>etc.</dd>
    </dl>
</div>

在开始试图拔出田地时,我开始说:

for item in g_data:
    try:
        print(item.contents[0].find_all("h4",{"class": "school_data"})[0].text)
    except:
        pass
    try:
        schoolType = item.contents[1].find("dt", text="School Type: ")
        print(schoolType.find_next_sibling("dd").text)
    except:
        pass

对于学校名称(h4标签),我希望上面打印第一个h4标签中的文本&#34;内容&#34;但它没有返回任何东西。我做了最终让它从h4标签打印文本只是通过这样做:

print(item.contents[0].text)

这有局限性......为什么没有原作?

对于schoolType部分(循环中的第二次尝试),我得到一个&#34; TypeError:find()不接受关键字参数&#34;。我读了一下,但看到别人推荐这个,我不确定为什么会出错。我怀疑我也做错其他的东西......例如,当我尝试简单地打印出item.contents [1]进行调试时,我得到了一堆空行。

有任何帮助吗?接下来,我将为数据创建变量并将其写入csv。 python和stackoverflow的新手,谢谢。

1 个答案:

答案 0 :(得分:0)

如果您希望 dl 标记内的子项中的所有文本都是前一个 h4 cyan_header 的兄弟,那么您只需从dls中提取子标记:< / p>

h = """<div class="school_data">
    <h4 class="cyan_header">Coop Tech<br/></h4>
    <dl>
        <dt>School Type: </dt>
        <dd>Academic</dd>
        <dt>Another Heading: </dt>
        <dd>etc.</dd>
    </dl>
</div>"""


from bs4 import BeautifulSoup, Tag
soup = BeautifulSoup(h)

h4s = soup.select("div.school_data h4.cyan_header")
for h4 in h4s:
    print([child.text for child in h4.find_next("dl").children if isinstance(child, Tag)] )

哪会给你:

[u'School Type: ', u'Academic', u'Another Heading: ', u'etc.']

为什么获得find() takes no keyword arguments"是因为item.contents[1]是字符串而不是标记,因此您实际上是在调用str.find

此外,如果您只想要返回一个标记,则应使用 find 而非 find_all ,find会给您一个匹配,第一个匹配。

您还可以使用dl标记提取所有dd标签和dt标签:

h4s = soup.select("div.school_data h4.cyan_header")
for h4 in h4s:
    dl = h4.find_next("dl")
    dds = dl.find_all("dd")
    dts = dl.find_all("dt")
    print(dds)
    print(dts)

哪会给你:

[<dd>Academic</dd>, <dd>etc.</dd>]
[<dt>School Type: </dt>, <dt>Another Heading: </dt>]

你使用什么完全取决于你想要什么以及html的其余部分是如何构建的,另外你应该做的另一件事是使用空白,除非至少打印/记录任何错误。