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

时间:2017-04-01 01:10:04

标签: python html parsing web-scraping beautifulsoup

我正在为this problem创建一个python解决方案,但我无法通过一些边缘案例。

我遇到的问题出现在像this这样的网页上,其中this link是应该提取的,因为它是括号外的第一个。{3}}。相反,有些文章是like this,其中链接出现在第一个括号之前。

我目前处理这些案例的方式是首先迭代第一段标记(字符串化版本)中的元素和文本,并检查首先在&#39;之间找到哪些(&#39; ;和一个<a>。如果首先找到<a>(意思是在到达括号之前),我只取这个链接。如果先找到括号,我等到括号关闭然后采取以下措施&#39;

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

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

我认为在这里工作的是使用这样的select语句从<p>的开头到第一个括号中找到前缀中的第一个链接,或者(如果在那里没有&#39; ta链接)使用与我目前正在做的事情类似的东西,在紧密括号后面找到紧跟的链接:

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

如果要使用这种方法,会出现多个问题,包括: 1.如何实际获得前缀直到第一个括号,只有&#39;的直接子元素。

有简化的方法吗?如果有更好的方法,它会是什么?

1 个答案:

答案 0 :(得分:3)

当您需要检查括号或其他括号是否平衡时,此问题提醒我流行的算法和数据结构问题。对于这些问题,堆栈数据结构使用起来很方便。

因此,在这种情况下,如果有一个左括号,我们将推送到堆栈,如果有一个关闭的,则从中弹出。我们的有效链接是堆栈为空时的链接

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

为#34;现代希腊语&#34;打印dialects页面和linguistics for&#34; Diglossia&#34;。这两种情况都得到了处理。