python-美丽的汤-在文章中找到第一个链接

我正在为this problem创建python解决方案,但是我无法克服一些极端情况.

我遇到的问题出现在诸如this之类的页面上,其中this link是应该提取的页面,因为它是括号之外的第一个页面.相反,有些文章是like this,其中链接出现在第一个括号之前.

当前,我处理这些情况的方式是,首先迭代第一个段落标签(字符串化版本)中的元素和文本,然后检查看哪个首先在'(‘和< a>之间找到.首先找到a>(意味着在到达括号之前),我只是采用了该链接.如果首先找到了括号,则等待直到括号被关闭,然后采用以下’

实际上,我只是得到第一段元素的直接子元素,可以通过以下方式完成:

soup = BeautifulSoup(response.content, "lxml")
soup.select_one("#mw-content-text > p > a")

我认为在这里起作用的是使用这样的select语句从p开头的前缀中找到前缀中的第一个链接.直到第一个括号或(如果前缀中没有链接)使用类似于我当前正在执行的操作在紧括号之后立即找到链接:

`findNext('a').attrs['href']`

如果要使用这种方法,则会出现多个问题,包括:
1.如何仅使用’的直接子元素来实际获取直到第一个括号的前缀

是否有简化的方式来做到这一点?如果有更好的方法,那会是什么?

解决方法:

这个问题提醒我,当您需要检查括号或其他括号是否平衡时,流行的算法和数据结构问题.对于此类问题,堆栈数据结构易于使用.

因此,在这种情况下,如果有一个圆括号,我们将压入堆栈,如果有一个圆括号将其弹出.当堆栈为空时,对我们而言有效的链接是:

import requests
from bs4 import BeautifulSoup, NavigableString, Tag


urls = [
    "https://en.wikipedia.org/wiki/Modern_Greek",
    "https://en.wikipedia.org/wiki/Diglossia"
]

with requests.Session() as session:
    for url in urls:
        response = session.get(url)
        soup = BeautifulSoup(response.content, "html.parser")

        stack = []
        for child in soup.select_one("#mw-content-text > p").children:
            if isinstance(child, NavigableString):
                if "(" in child:
                    stack.append("(")
                if ")" in child:
                    stack.pop()

            if isinstance(child, Tag) and child.name == "a" and not stack:
                print(child.get_text())
                break

它为“现代希腊语”页面打印方言,为“ Diglossia”页面打印语言.两种情况都可以处理.

上一篇:Python-如何使用Beautiful Soup查找ID为“ value”的所有跨度的文本?


下一篇:python bs4在没有硒的弹出窗口中获取元素