使用BeautifulSoup的Web scraper不工作



我已经为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)

可能建议使用上面的方法来更深入地理解响应结构,以便在解析过程中最好忽略这些元素。

当然,你总是可以像下面这样对循环中抛出的任何AttributeErrorpass做一些懒惰的处理,但仍然可以打印抛出的任何其他类型的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))

最新更新