我已经为Stack Overflow编写了一个web scraper,但它不起作用。显然,在我的汤里有一些不知道从哪里来的NoneType对象。下面是web scraper代码:
import requests
from bs4 import BeautifulSoup
url = 'https://stackoverflow.com/questions?tab=newest&page='
r = requests.post(url)
soup = BeautifulSoup(r.text, 'lxml').find('div', id='questions').find_all('div')
for summary in soup: # FIXME: Prints each question twice
try:
print(f'Question: {summary.h3.text}')
print(f'Tags: {", ".join(summary.find("div", class_="tags").text[1:].split(" "))}')
except Exception as e:
print(e) # Prints "'NoneType' has no attribute 'text'" which shouldn't be in the soup
我得到的错误(如果你没有阅读评论)是"'NoneType'没有属性'text'"这让我很困惑,因为汤里有NoneType对象。
我正在使用:
Windows 10- Python 3.8
在soup
中没有None
类型的对象,而是对
... summary.h3 ...
... summary.find("div", class_="tags") ...
在你的循环中,如果summary
没有h3
元素,或者如果在当前的summary
中没有div
元素具有tags
的类属性,将返回None
。
在这些情况下,当您试图访问None
类型元素的text
属性时,自然会抛出Exception
。
使用enumerate
来显示导致Exception
抛出的soup
的索引可能会有所帮助。
。
for i, summary in enumerate(soup):
try:
print(f'Question: {summary.h3.text}')
print(f'Tags: {", ".join(summary.find("div", class_="tags").text[1:].split(" "))}')
except Exception as e:
print(f'Exception raised during handling of soup[{i}]')
print(e)
可能建议使用上面的方法来更深入地理解响应结构,以便在解析过程中最好忽略这些元素。
当然,你总是可以像下面这样对循环中抛出的任何AttributeError
的pass
做一些懒惰的处理,但仍然可以打印抛出的任何其他类型的Exception
——尽管这显然不是最有效的方法。
for summary in soup:
try:
print(f'Question: {summary.h3.text}')
print(f'Tags: {", ".join(summary.find("div", class_="tags").text[1:].split(" "))}')
except AttributeError as ee:
pass
except Exception as e:
print(e)
JP193已经给了你关于为什么你得到一个NoneType
返回的答案。
我在你的代码中发现的大问题是,你使用BeautifulSoup(r.text,xml').find('div', id='questions').find_all('div')
找到的每个<div>
都不需要获得"问题"。和"标签",这就是为什么你会收到很多AttributeError
消息。为了浓缩<div>
,您需要更仔细地查看soup
的结果代码。为了最好地浓缩soup
的结果,将找到所有<div>
,其中class
为"question-summary"
。所以代码应该看起来更像:
soup = BeautifulSoup(r.content, "html.parser").find("div", id="questions").find_all("div", {"class": "question-summary"})
在那之后,就由你决定如何打印'question'和'tags'的结果了。我是这样做的:
try:
question = q.find("div", {"class": "summary"}).find('h3')
print('Question: ' + question.text)
tags = soup[0].find("div", {"class": "tags"}).text.split()
print('Tags: ' + ', '.join(tags))
except AttributeError:
print('AttributeError div ' + str(int + 1))
我的解决方案是:
from bs4 import BeautifulSoup
url = 'https://stackoverflow.com/questions?tab=newest&page='
r = requests.get(url)
soup = BeautifulSoup(r.content, "html.parser").find("div", id="questions").find_all("div", {"class": "question-summary"})
for int, q in enumerate(soup):
try:
question = q.find("div", {"class": "summary"}).find('h3')
print('Question: ' + question.text)
tags = soup[0].find("div", {"class": "tags"}).text.split()
print('Tags: ' + ', '.join(tags))
except AttributeError:
print('AttributeError div ' + str(int + 1))