我正在为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”页面打印语言.两种情况都可以处理.