代码之家  ›  专栏  ›  技术社区  ›  bill999

python-beautifulsoup-在标记之间查找可变数量的文本

  •  0
  • bill999  · 技术社区  · 11 年前

    我使用python+beautifulsoup来解析html。我的问题是我有可变数量的文本项。例如,在这种情况下,我想提取“文本1”、“文本2”文本4’。在其他网页中,可能只有“文本1”,也可能有两个,等等。所以它会改变。如果“文本x”包含在标签中,我的生活会更轻松。但事实并非如此。我可以使用next和previousSibling(或者nextSibling和previous Sibling)访问它们,但我不知道如何获取所有这些。这个想法是(假设我遇到的最大数字是四)将“文本1”写入一个文件,然后一直进行到“文本4”。在这种情况下就是这样。在只有“文本1”的情况下,我会在文件中写“文本1“,然后只留下2-4的空白。对我该怎么做有什么建议吗?

    <div id="DIVID" style="display: block; margin-left: 1em;">
      <b>Header 1</b>
      <br/>
      Text 1
      <br/>
      Text 2
      <br/>
      Text 3
      <br/>
      Text 4
     <br/>
     <b>Header 2</b>
    </div>
    

    当我在做的时候,我有一个不那么相关的问题。假设我有一个网站,它有一个可变数量的链接,所有链接到html的链接都和我上面的完全一样。这个应用程序不是这样的,但想想craigslist吧——中央页面上有很多链接。我需要能够访问这些页面中的每一个,以便进行解析。这样做的好方法是什么?

    谢谢

    额外: 下一个网页可能如下所示:

    <div id="DIVID2" style="display: block; margin-left: 1em;">
      <b>Header 1</b>
      <br/>
      Different Text 1
      <br/>
      Different Text 2
     <br/>
     <b>Header 2</b>
    </div>
    

    注意差异:

    1. DIVID现在是DIVID2。我可以根据页面上的其他解析来计算DIVID上的结尾。这不是问题。

    2. 我只有两条文字,而不是四条。

    3. 现在的文本不同了。

    注意关键的相似性:

    1. 收割台1和收割台2相同。这些不会改变。
    3 回复  |  直到 11 年前
        1
  •  2
  •   justhalf    11 年前

    你可以使用 get_text :

    test ="""<div id='DIVID'>
    <b>Header 1</b>
    <br/>
    Text 1
    <br/>
    Text 2
    <br/>
    Text 3
    <br/>
    Text 4
    <br/>
    <b>Header 2</b>
    </div>"""
    
    def divid(tag):
        return tag.name=='div' and tag.has_attr('id') and tag['id'].startswith('DIVID')
    
    soup = BeautifulSoup(test)
    print soup.find(divid).get_text()
    

    哪个会给你

    Header 1
    
    Text 1
    
    Text 2
    
    Text 3
    
    Text 4
    
    Header 2
    
    
        2
  •  1
  •   erewok    11 年前

    你可以试试这样的方法:

    >>> test ="""<b>Header 1</b>
    <br/>
    Text 1
    <br/>
    Text 2
    <br/>
    Text 3
    <br/>
    Text 4
    <br/>
    <b>Header 2</b>"""
    >>> soup = BeautifulSoup(test)
    
    >>> test = soup.find('b')
    >>> desired_text = [x.strip() for x in str(test.parent).split('<br />')]
    ['<b>Header 1</b>', 'Text 1', 'Text 2', 'Text 3', 'Text 4', '<b>Header 2</b>']
    

    现在你只需要通过你的“标题”块来区分,我认为这是可行的,我相信这可能会让你朝着正确的方向开始。

    至于你的另一个问题,你需要组装一个链接列表,然后在它们之间迭代,逐个打开每个链接,并按照你的意愿进行处理。不过,这是一个更广泛的问题,所以你应该尝试一些东西,然后回来完善你所拥有的,一旦你在某个特定问题上需要帮助,就提出一个新的问题。


    最后一行代码说明:

    [x.strip() for x in str(test.parent).split('<br />')]
    

    这将获取我在上面分配的“测试”节点,并获取父节点。通过变成一根绳子,我可以在 <br> 标签,这会使这些标签消失,并将我们想要分离的所有文本分离。这会创建一个列表,其中每个列表项都有我们想要的文本和一些'\n'。

    最后,最令人困惑的可能是列表理解语法,它看起来像这样:

    some_list = [item for item in some_iterable]
    

    这只是生成一个“item”的列表,所有这些都取自“some_iterable”。在我对列表的理解中,我正在浏览列表,获取列表中的每一项,然后简单地去掉一行换行符( x.strip() 部分)。顺便说一句,有很多方法可以做到这一点。

        3
  •  1
  •   Vorsprung    11 年前

    这里有一个不同的解决方案。nextSibling可以获取结构化文档中命名标记后面的部分。

    from BeautifulSoup import BeautifulSoup
    
    text="""
    <b>Header 1</b>
    <br/>
    Text 1
    <br/>
    Text 2
    <br/>
    Text 3
    <br/>
    Text 4
    <br/>
    <b>Header 2</b>
    """
    
    soup = BeautifulSoup(text)
    
    for br in soup.findAll('br'):
        following = br.nextSibling
        print following.strip()