【问题标题】:Python + selenium: extract variable quantity of paragraphs between titlesPython + selenium:提取标题之间可变数量的段落
【发布时间】:2015-11-26 20:12:42
【问题描述】:

各位大侠,假设下面的html如何提取属于<h3>的图块<p>的段落。

<!DOCTYPE html>
    <html>
    <body>
    ...
        <div class="main-div">
            <h3>Title 1</h3>
            <p></p>
        
            <h3>Title 2</h3>
            <p></p>
            <p></p>
            <p></p>
            
            <h3>Title 3</h3>
            <p></p>
            <p></p>
            ...
        </div>
</body>

如您所见,&lt;h3&gt;&lt;p&gt; 标记都是 &lt;div&gt; 标记的子标记但它们没有类或 id 可以识别它们并说“标题 1 " 有 1 段,标题 2 有 3 段,标题 3 有 2 段,依此类推。我看不到将段落与标题联系起来的方法...

我正在尝试使用 Python 2.7 + selenium。但我不确定我使用的是正确的工具,也许您可​​以提出解决方案或任何不同的组合,如 Beautifulsoup、urllib2...

任何建议/方向将不胜感激!


更新

在@JustMe 指出的出色解决方案之后,我想出了下面的解决方案,希望它对其他人有所帮助,或者如果有人可以将其改进为 pythonic。我来自 c/c++/java/perl 世界,所以我总是碰壁:)

import bs4

page = """ 
<!DOCTYPE html>
<html>
<body>
...
    <div class="maincontent-block">
        <h3>Title 1</h3>
        <p>1</p>
        <p>2</p>
        <p>3</p>

        <h3>Title 2</h3>
        <p>2</p>
        <p>3</p>
        <p>4</p>

        <h3>Title 3</h3>
        <p>7</p>
        <p>9</p>
        ...
    </div>
</body>
"""

page = bs4.BeautifulSoup(page, "html.parser")
div = page.find('div', {'class':"maincontent-block"})

mydict = {}

# write to the dictionary
for tag in div.findChildren():
    if (tag.name == "h3"):
        #print(tag.string)
        mydict[tag.string] = None
        nextTags = tag.findAllNext()
        arr = [];
        for nt in nextTags:
            if (nt.name == "p"):
                arr.append(nt.string)
                mydict[tag.string] = arr
            elif (nt.name == "h3"):
                arr = []
                break

# read from dictionary
arrKeys = []
for k in mydict:
    arrKeys.append(k)

arrKeys.sort()
for k in arrKeys:
    print k
    for v in mydict[k]:
        print v

【问题讨论】:

  • 你的答案与硒无关。更新问题的标题和标签。
  • 我想用 selenium 来做,但我做不到,所以问题还是一样。也许有人可以通过解决方案删除一两行。

标签: python html selenium beautifulsoup urllib2


【解决方案1】:

使用 BeautifulSoup 很容易做到

import bs4

page = """
<!DOCTYPE html>
    <html>
    <body>
    ...
        <div class="main-div">
            <h3>Title 1</h3>
            <p></p>

            <h3>Title 2</h3>
            <p></p>
            <p></p>
            <p></p>

            <h3>Title 3</h3>
            <p></p>
            <p></p>
            ...
        </div>
</body>
"""

page = bs4.BeautifulSoup(page)
h3_tag = page.div.find("h3").string
print(h3_tag)
>>> u'Title 1'

h3_tag.find_next_siblings("p")
>>> [<p></p>, <p></p>, <p></p>, <p></p>, <p></p>, <p></p>]
len(h3_tag.find_next_siblings("p"))/2
>>> 3

好的,既然你想要分开的段落计数,我想出了这个,粗鲁的东西。

 h_counters = []
 count = -1
 for child in page.div.findChildren():
     if "<h3>" in str(child):
         h_counters.append(count)
         count = 0
     else:
         count += 1
 h_counters.append(count)
 h_counters = h_counters[1:]
 print (h_counters)
 >> [1, 3, 2]

【讨论】:

  • 这是一个很好的解决方案,但这正是我所在的地方。我正在寻找一些解决方案,我可以将标题 1 下方的段落关联到标题 1,然后将标题 2 下方的三个段落关联到标题 2,依此类推。由于&lt;p&gt; 不是&lt;h3&gt; 的子级,并且h3 没有标识它的ID,所以我不知道如何实现它。
  • 我已经编辑了我的答案,这有帮助吗?嗯,不,等等你只想要一个。让我看看。
  • 不,你是对的!我们就快到了。我正在寻找一种表达方式,例如:这些段落属于这个标题。由于段落的数量是可变的,无论标题如何,都很难完成。顺便说一句,我已经尝试了 find_next_siblings("p") ,但它会返回所有段落。也许我们可以调用 findNext() 并针对&lt;p&gt;&lt;h3&gt; 测试每个结果,你觉得呢?
  • 我已经阅读了一些文档,但没有发现任何好的东西......所以想出了迭代方法......我猜不是那么漂亮,但是嘿,它至少可以工作 ;)
  • 太棒了!谢谢你的朋友,希望有一天我能以某种方式帮助你。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-05-10
  • 1970-01-01
相关资源
最近更新 更多