TypeError: 使用BeautifulSoup时调用split操作的'NoneType'对象错误
今天我在玩BeautifulSoup和Requests这两个工具,所以我想写一个简单的爬虫,能够跟踪网页上的链接,深度为2(如果这样说能让你明白的话)。我抓取的网页里的所有链接都是相对链接。(比如说:<a href="/free-man-aman-sethi/books/9788184001341.htm" title="A Free Man">
)为了把这些相对链接变成绝对链接,我想用urljoin
把网页的地址和相对链接连接起来。
为了做到这一点,我首先需要从<a>
标签中提取出href的值,为此我想用split
来处理:
#!/bin/python
#crawl.py
import requests
from bs4 import BeautifulSoup
from urlparse import urljoin
html_source=requests.get("http://www.flipkart.com/books")
soup=BeautifulSoup(html_source.content)
links=soup.find_all("a")
temp=links[0].split('"')
但是这给我带来了以下错误:
Traceback (most recent call last):
File "test.py", line 10, in <module>
temp=links[0].split('"')
TypeError: 'NoneType' object is not callable
在没有仔细阅读文档之前就开始动手,我意识到这可能不是实现我目标的最佳方法,但为什么会出现TypeError这个错误呢?
3 个回答
1
我刚遇到了同样的错误,所以四年后分享一下经验:如果你需要把 soup 元素分开,你也可以在分开之前先用 str() 把它转换成字符串。在你的情况下,可以这样做:
temp = str(links).split('"')
1
因为Tag
这个类使用了一种叫做代理的方式来访问属性(正如Pavel所提到的,这种方式是为了尽可能访问子元素),所以如果找不到对应的属性,就会返回一个默认值None
。
复杂的例子:
>>> print soup.find_all('a')[0].bob
None
>>> print soup.find_all('a')[0].foobar
None
>>> print soup.find_all('a')[0].split
None
你需要使用:
soup.find_all('a')[0].get('href')
其中:
>>> print soup.find_all('a')[0].get
<bound method Tag.get of <a href="test"></a>>
6
links[0]
不是一个字符串,它是一个 bs4.element.Tag
对象。当你试图在它上面使用 split
方法时,它会去找一个叫 split
的子元素,但实际上并没有这个子元素。所以你得到的结果是 None。
In [10]: l = links[0]
In [11]: type(l)
Out[11]: bs4.element.Tag
In [17]: print l.split
None
In [18]: None() # :)
TypeError: 'NoneType' object is not callable
可以用索引来查找 HTML 属性:
In [21]: links[0]['href']
Out[21]: '/?ref=1591d2c3-5613-4592-a245-ca34cbd29008&_pop=brdcrumb'
或者使用 get
方法,这样可以避免找不到属性的情况:
In [24]: links[0].get('href')
Out[24]: '/?ref=1591d2c3-5613-4592-a245-ca34cbd29008&_pop=brdcrumb'
In [26]: print links[0].get('wharrgarbl')
None
In [27]: print links[0]['wharrgarbl']
KeyError: 'wharrgarbl'