【问题标题】:TypeError: must be str, not NoneTypeTypeError:必须是 str,而不是 NoneType
【发布时间】:2022-01-27 16:48:53
【问题描述】:

我正在编写我的第一个“真实”项目,一个网络爬虫,但我不知道如何解决这个错误。这是我的代码

import requests
from bs4 import BeautifulSoup

def main_spider(max_pages):
    page = 1
    for page in range(1, max_pages+1):
        url = "https://en.wikipedia.org/wiki/Star_Wars" + str(page)
        source_code = requests.get(url)
        plain_text = source_code.text
        soup = BeautifulSoup(plain_text, "html.parser")
        for link in soup.findAll("a"):
            href = "https://en.wikipedia.org/wiki/Star_Wars" + link.get("href")
            print(href)
    page += 1

main_spider(1)

这是错误

href = "https://en.wikipedia.org/wiki/Star_Wars" + link.get("href")
TypeError: must be str, not NoneType  

【问题讨论】:

  • 你检查过 link.get("href") 是否返回了一个字符串吗?您的代码没有正确缩进。
  • 我很抱歉这么愚蠢,我似乎已经解决了它,但现在我遇到了一个新问题。我不是从页面中获取所有链接,而是一遍又一遍地获取原始页面的 url。
  • 怎么来的?你缩进了 main_spider(1) 并且你不应该得到任何东西。或者你有两条 main_spider(1) 行,一条在函数本身?
  • @MSeifert 好的。对于本示例,link.get("href") 将返回 None。

标签: python


【解决方案1】:

正如@Shiping 所指出的,您的代码没有正确缩进......我在下面更正了它。 另外...link.get('href') 在其中一种情况下没有返回字符串。

import requests
from bs4 import BeautifulSoup

def main_spider(max_pages):
    for page in range(1, max_pages+1):
        url = "https://en.wikipedia.org/wiki/Star_Wars" + str(page)
        source_code = requests.get(url)
        plain_text = source_code.text
        soup = BeautifulSoup(plain_text, "html.parser")
        for link in soup.findAll("a"): 

            href = "https://en.wikipedia.org/wiki/Star_Wars" + link.get("href")
            print(href)

main_spider(1)

为了评估正在发生的事情,我添加了几行代码...在您现有的几行之间并删除了有问题的行(暂时)。

        soup = BeautifulSoup(plain_text, "html.parser")
        print('All anchor tags:', soup.findAll('a'))     ### ADDED
        for link in soup.findAll("a"): 
            print(type(link.get("href")), link.get("href"))  ### ADDED

我添加的结果是这样的(为简洁起见被截断): 注意:第一个锚点没有 href 属性,因此 link.get('href') 不能返回值,所以返回 None

[<a id="top"></a>, <a href="#mw-head">navigation</a>, 
<a href="#p-search">search</a>, 
<a href="/wiki/Special:SiteMatrix" title="Special:SiteMatrix">sister...   
<class 'NoneType'> None
<class 'str'> #mw-head
<class 'str'> #p-search
<class 'str'> /wiki/Special:SiteMatrix
<class 'str'> /wiki/File:Wiktionary-logo-v2.svg      
...

为防止该错误,一种可能的解决方案是在您的代码中添加一个条件 OR 一个 try/except 表达式。我将演示一个条件表达式。

        soup = BeautifulSoup(plain_text, "html.parser")
        for link in soup.findAll("a"): 
            if link.get('href') == None:
                continue
            else:
                href = "https://en.wikipedia.org/wiki/Star_Wars" + link.get("href")
                print(href) 

【讨论】:

  • 太棒了,完美运行!但是,有没有办法可以将我返回的链接限制为仅关于《星球大战》的链接?考虑到它是为页面上的每个链接设置的,我可以将输出限制为主要链接吗?
【解决方案2】:

维基百科页面上的第一个“a”链接是

<a id="top"></a>

因此,link.get("href") 将返回 None,因为没有 href。

要解决此问题,请先检查无:

if link.get('href') is not None:
    href = "https://en.wikipedia.org/wiki/Star_Wars" + link.get("href")
    # do stuff here

【讨论】:

    【解决方案3】:

    并非所有锚点(&lt;a&gt; 元素)都需要具有href 属性(请参阅https://www.w3schools.com/tags/tag_a.asp):

    在 HTML5 中,标签始终是超链接,但如果它没有 href 属性,则它只是超链接的占位符。

    实际上你已经得到了异常,而 Python 非常擅长处理异常,那么为什么不捕获异常呢?这种风格被称为"Easier to ask for forgiveness than permission." (EAFP),实际上是被鼓励的:

    import requests
    from bs4 import BeautifulSoup
    
    def main_spider(max_pages):
        for page in range(1, max_pages+1):
            url = "https://en.wikipedia.org/wiki/Star_Wars" + str(page)
            source_code = requests.get(url)
            plain_text = source_code.text
            soup = BeautifulSoup(plain_text, "html.parser")
            for link in soup.findAll("a"):
                # The following part is new:
                try:
                    href = "https://en.wikipedia.org/wiki/Star_Wars" + link.get("href")
                    print(href)
                except TypeError:
                    pass
    
    main_spider(1)
    

    page = 1page += 1 行也可以省略。 for page in range(1, max_pages+1): 指令到这里就已经足够了。

    【讨论】:

    • @DylanBoyd 我更新了答案。我不知道它如何导致 SyntaxError 但缩进或复制过程中可能出现问题。 :)
    • 我最终将上面的答案与 else 语句一起使用。谢谢你的帮助
    • @DylanBoyd 如果您选择其他答案没问题 - 但如果您想使用条件我会推荐 Jackywathys answer 代替。 continue 是不必要的,然后你不需要 else
    • 哦,你是对的,这种方式也很好用!再次感谢
    【解决方案4】:

    我在不同的代码中遇到了同样的错误。在函数内添加条件后,我认为返回类型设置不正确,但我意识到当条件为 False 时,根本没有调用 return 语句——对缩进的更改修复了问题。

    【讨论】:

      【解决方案5】:

      在类似的情况下,我收到了相同的错误消息。

      我也在连接字符串,并且应该为一个变量分配一个函数的返回值。

      但在一种情况下,没有返回值并且变量是“空的”。这导致了相同的错误消息。

      input = get_input() # <-- make sure this always returns a value
      print ("input was" + input)
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-11-22
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多