BeautifulSoup - TypeError: 'NoneType'对象不可调用

13 投票
2 回答
44555 浏览
提问于 2025-04-30 02:39

我需要让我的代码能够在python2.6和BeautifulSoup 3上运行。我的代码是用python2.7写的,并且使用了BS4。但是当我在squeezy服务器上运行它时,出现了这个错误(服务器上是python2.6和bs3):

try:
    from bs4 import BeautifulSoup
except ImportError:
    from BeautifulSoup import BeautifulSoup

gmp = open(fname, 'r')
soup = BeautifulSoup(gmp)
p = soup.body.div.find_all('p')

p = soup.body.div.find_all('p')
TypeError: 'NoneType' object is not callable

如果我改成:

   p = soup.body.div.findAll('p')

那么我就会得到这个错误:

p = soup.body.div.findAll('p')
TypeError: 'NoneType' object is not callable

错误更新

  File "/home/user/openerp/7.0/addons/my_module/models/gec.py", line 401, in parse_html_data
    p = soup.body.div.findAll('p') #used findAll instead of find_all for backwards compatability to bs3 version
TypeError: 'NoneType' object is not callable

无论哪种方法,在我的Ubuntu上用python2.7和bs4都能正常工作,但在squeezy上却不行。难道在这些版本之间还有我看不见/不知道的其他区别,导致了这个错误吗?

暂无标签

2 个回答

0

我知道这是一篇六年前的帖子,但我还是想发出来,以防有人遇到类似的问题。

看起来在第9行应该是一个格式化字符串,添加了f之后,它似乎工作得很好。

import pandas as pd
import numpy as np
import requests
from bs4 import BeautifulSoup

product_all_pages = []

for i in range(1,15):
    response = requests.get(f"https://www.bol.com/nl/s/?page={i}&searchtext=hand+sanitizer&view=list")
    content = response.content
    parser = BeautifulSoup(content, 'html.parser')
    body = parser.body
    producten = body.find_all(class_="product-item--row js_item_root")
    product_all_pages.extend(producten)
len(product_all_pages)

price = float(product_all_pages[1].meta.get('content'))
productname = product_all_pages[1].find(class_="product-title--inline").a.getText()
print(price)
print(productname)

productlijst = []

for item in product_all_pages:
    if item.find(class_="product-prices").getText() == '\nNiet leverbaar\n':
        price = None
    else:
        price = float(item.meta['content'])
    product = item.find(class_="product-title--inline").a.getText()
    productlijst.append([product, price])
    
print(productlijst[:3])

df = pd.DataFrame(productlijst, columns=["Product", "price"])
print(df.shape)
df["price"].describe()
25

你现在使用的是BeautifulSoup 3,但却在用BeautifulSoup 4的写法。

你的备用方案出了问题:

try:
    from bs4 import BeautifulSoup
except ImportError:
    from BeautifulSoup import BeautifulSoup

如果你想用3或4版本,建议你坚持使用3版本的写法:

p = soup.body.div.findAll('p')

因为在BeautifulSoup 3中,find_all这个方法是不存在的,所以它会被当作标签搜索来处理。而你的HTML中没有find_all这个标签,所以返回的结果是None,接着你又试图去调用它。

接下来,BeautifulSoup 3使用的解析器对破损或不完整的HTML的反应会有所不同。如果你在Ubuntu上安装了lxml,那么它会被用作默认的解析器,并且会为你插入缺失的<body>标签。而BeautifulSoup 3可能就不会插入这个标签。

我强烈建议你去掉备用方案,只使用BeautifulSoup 4 即可。3版本早就停止更新了,而且里面还有一些未修复的bug。BeautifulSoup 4还提供了你可能想用的额外功能。

BeautifulSoup是纯Python写的,可以很容易地安装到任何支持Python的平台上的虚拟环境里。你不需要依赖系统自带的包。

比如在Debian Squeezy上,你只能用BeautifulSoup 3.1.0,甚至连BeautifulSoup的开发者也不希望你使用它!。你在使用findAll时遇到的问题几乎肯定是因为用到了这个版本。

撰写回答