【问题标题】:Finding direct child of an element查找元素的直接子元素
【发布时间】:2017-08-26 07:50:40
【问题描述】:

我正在编写一个解决方案来测试 Python 中的this 现象。我已经完成了大部分逻辑,但是在跟踪 Wikipedia 文章中的链接时会出现许多边缘情况。

我遇到的问题出现在像this 这样的页面上,其中第一个<p> 具有多个级别的子元素,并且需要提取第一组括号之后的第一个<a> 标记。在这种情况下,(要提取this link),您必须跳过括号,然后到达下一个锚标记/href。在大多数文章中,我的算法可以跳过括号,但是由于它在括号前查找链接(或者如果它们不存在),它会在错误的位置找到锚标记。具体来说,这里:<span style="font-size: small;"><span id="coordinates"><a href="/wiki/Geographic_coordinate_system" title="Geographic coordinate system">Coordinates</a>

该算法通过迭代第一个段落标签中的元素(在文章的主体中),迭代地对每个元素进行字符串化,并首先检查它是否包含'('或'

是否有任何直接的方法可以避免嵌入锚标记,而只采用第一个链接,该链接是第一个 <p> 的直接子节点?

下面是带有此代码的函数供参考:

**def getValidLink(self, currResponse):
        currRoot = BeautifulSoup(currResponse.text,"lxml")
        temp = currRoot.body.findAll('p')[0]
        parenOpened = False
        parenCompleted = False
        openCount = 0
        foundParen = False
        while temp.next:
            temp = temp.next
            curr = str(temp)
            if '(' in curr and str(type(temp)) == "<class 'bs4.element.NavigableString'>":
                foundParen = True
                break
            if '<a' in curr and str(type(temp)) == "<class 'bs4.element.Tag'>":
                link = temp
                break

        temp = currRoot.body.findAll('p')[0]
        if foundParen:
            while temp.next and not parenCompleted:
                temp = temp.next
                curr = str(temp)
                if '(' in curr:
                    openCount += 1
                    if parenOpened is False:
                        parenOpened = True
                if ')' in curr and parenOpened and openCount > 1:
                    openCount -= 1
                elif ')' in curr and parenOpened and openCount == 1:
                    parenCompleted = True
            try:
                return temp.findNext('a').attrs['href']
            except KeyError:
                print "\nReached article with no main body!\n"
                return None
        try:
            return str(link.attrs['href'])
        except KeyError:
            print "\nReached article with no main body\n"
            return None**

【问题讨论】:

    标签: python html dom web-scraping beautifulsoup


    【解决方案1】:

    我认为你严重地把问题复杂化了。

    有多种方法可以使用BeautifulSoup 中元素之间的直接父子关系。一种方法是&gt;CSS selector

    In [1]: import requests  
    
    In [2]: from bs4 import BeautifulSoup   
    
    In [3]: url = "https://en.wikipedia.org/wiki/Sierra_Leone"    
    
    In [4]: response = requests.get(url)    
    
    In [5]: soup = BeautifulSoup(response.content, "html.parser")
    
    In [6]: [a.get_text() for a in soup.select("#mw-content-text > p > a")]
    Out[6]: 
    ['West Africa',
     'Guinea',
     'Liberia',
     ...
     'Allen Iverson',
     'Magic Johnson',
     'Victor Oladipo',
     'Frances Tiafoe']
    

    在这里,我们发现 a 元素位于 p 元素的正下方,位于 id="mw-content-text" 元素的正下方 - 据我了解,这是维基百科主要文章所在的位置。

    如果您需要单个元素,请使用 select_one() 而不是 select()

    另外,如果您想通过find*() 解决它,请传递recursive=False 参数。

    【讨论】:

    • 感谢您的回复!这在您不必担心括号的情况下确实有效,但如果括号首先出现在段落中,则需要其他逻辑。此外,有时链接会被包裹在一个粗体标签中,因为它是here。有没有获取此链接的通用方法?
    • 实际上,我认为这种现象只有在您选择括号后的第一个链接而不是斜体/粗体时才会出现,因此该解决方案可能适用于我刚才提到的链接。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-13
    • 1970-01-01
    • 2018-07-09
    • 2014-08-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多