Python + BeautifulSoup: 如何获取‘a’元素的‘href’属性?

23

我有以下内容:

  html =
  '''<div class=“file-one”>
    <a href=“/file-one/additional” class=“file-link">
      <h3 class=“file-name”>File One</h3>
    </a>
    <div class=“location”>
      Down
    </div>
  </div>'''

我想获得仅为href的文本,即/file-one/additional。因此我这样做:

from bs4 import BeautifulSoup

soup = BeautifulSoup(html, 'html.parser')

link_text = “”

for a in soup.find_all(‘a’, href=True, text=True):
    link_text = a[‘href’]

print “Link: “ + link_text

但它只打印了一个空白,什么也没有。只有Link:。因此,我在另一个具有不同HTML的站点上进行了测试,它可以正常工作。

我做错了什么?还是有可能站点被故意编程为不返回href吗?

提前感谢,我一定会投票/接受答案!


2
你的HTML里真的有花括号引号吗? - user2357112
1
就此而言,为什么你的代码里有花括号?你在用什么编写代码?你需要使用文本编辑器。 - user2357112
如果你移除参数 text=True,你的代码对我来说可以工作。 - chickity china chinese chicken
如果您需要更多关于引号的信息,请查看此文章:https://blogs.msdn.microsoft.com/oldnewthing/20090225-00/?p=19033 - Kyle Falconer
@downshift text=True 是什么意思?我以为它会返回文本形式。 - user3259472
显示剩余2条评论
6个回答

43

您的HTML中的'a'标签没有直接包含任何文本,但它包含一个带有文本的'h3'标签。这意味着text为None,并且.find_all()无法选择该标签。通常情况下,在标签包含除文本内容以外的其他HTML元素时,请勿使用text参数。

如果您仅使用标记名称(和href关键字参数)来选择元素,则可以解决此问题。然后在循环中添加条件检查它们是否包含文本。

soup = BeautifulSoup(html, 'html.parser')
links_with_text = []
for a in soup.find_all('a', href=True): 
    if a.text: 
        links_with_text.append(a['href'])

如果你更喜欢一行代码,你可以使用列表推导式。

links_with_text = [a['href'] for a in soup.find_all('a', href=True) if a.text]

或者你可以通过向.find_all()传递lambda来实现。

tags = soup.find_all(lambda tag: tag.name == 'a' and tag.get('href') and tag.text)
如果您想收集所有链接,无论它们是否有文本,只需选择具有“href”属性的所有'a'标签。锚点标签通常具有链接,但这不是必需的,因此我认为最好使用“href”参数。
使用.find_all()
links = [a['href'] for a in soup.find_all('a', href=True)]

使用 CSS 选择器与 .select() 方法。

links = [a['href'] for a in soup.select('a[href]')]

想告诉你一个我自己难以解决的问题。如果您能查看此帖子,我将非常高兴。谢谢。帖子链接:https://stackoverflow.com/questions/59594692/unable-to-use-https-proxy-within-urllib-request - MITHU
如果我需要打印这些链接中的每一个,该怎么办?因为它是一个列表,而不是字符串。 - Linces Marques
1
@LincesMarques 为什么不使用for循环?for link in links: print(link) - t.m.adam

6
你还可以使用attrs和正则表达式搜索来获取href标签。
soup.find('a', href = re.compile(r'[/]([a-z]|[A-Z])\w+')).attrs['href']

1
你知道为什么直接调用.href不起作用,但是.attrs['href']却可以正常工作吗?我刚刚花了15分钟来调试这个问题:( - Jean Monet

5
  1. 首先,使用不使用卷曲引号的不同文本编辑器。

  2. 其次,从soup.find_all中删除text=True标志。


3
你只需要用几行gazpacho代码就可以解决这个问题:

from gazpacho import Soup

html = """\
<div class="file-one">
    <a href="/file-one/additional" class="file-link">
      <h3 class="file-name">File One</h3>
    </a>
    <div class="location">
      Down
    </div>
  </div>
"""

soup = Soup(html)
soup.find("a", {"class": "file-link"}).attrs['href']

这将输出:

'/file-one/additional'

0
如果有人仍然不明白 href 的用法,可以试试这个。
  info=soup.find(‘a’, href=True):
  print (info.attrs.get("href"))

-1
有点晚了,但最近我也遇到了同样的问题,通过以下方法解决了网页内容采集后打印乱码的问题:
from bs4 import BeautifulSoup
import requests

source = requests.get('url for website')
soup = BeautifulSoup(source, 'lxml')

for article in soup.find_all('article'):
    link = article.find('a', href=True)['href'}
    print(link)

1
请自问 - 这个答案在根本上与之前的非常详细的答案有何不同,它的附加价值是什么。此外,请检查您的方法是否能够正常运行。这不是关于收集徽章,而是关于用好的答案帮助他人。 - HedgeHog
1
不是为了徽章或声望而在这里,只是遇到了相同的问题,并发布了最终为我工作的解决方案,尽管有其他各种帖子。 - Joseph Williams

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接