我正在编写一个在Python中测试this现象的解决方案。我已经完成了大部分逻辑,但是在维基百科文章中关注链接时会出现许多边缘情况。
我遇到的问题出现在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**
答案 0 :(得分:1)
我认为你严重过分复杂了这个问题。
有多种方法可以在BeautifulSoup
中使用元素之间的直接父子关系。一种方法是>
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
元素正下方元素的正下方{ - 1}} - 据我所知,这是维基百科的主要文章位于。
如果您需要单个元素,请使用id="mw-content-text"
代替select_one()
。
此外,如果您想通过select()
解决此问题,请传递recursive=False
参数。