【问题标题】:why i get the "'NoneType' object has no attribute" error为什么我得到“'NoneType'对象没有属性”错误
【发布时间】:2017-12-21 12:56:33
【问题描述】:

我制作了一个用于从网站上抓取一些数据的脚本,但它只运行了几页,之后它将停止并显示此消息“'NoneType' object has no attribute 'a'”。另一个错误是有时出现是这样的:

File "scrappy3.py", line 31, in <module>
f.writerow(doc_details)
File "C:\python\lib\encodings\cp1252.py", line 19, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode character '\u015f' in 
position 251: character maps to <undefined>

你能给我一个建议如何解决这些错误吗?这是我的脚本:

import requests
import csv
from bs4 import BeautifulSoup
import re
import time

start_time = time.time()
page = 1
f = csv.writer(open("./doctors.csv", "w", newline=''))
while page <= 5153:
    url = "http://www.sfatulmedicului.ro/medici/n_s0_c0_h_s0_e0_h0_pagina" + str(page)
    data = requests.get(url)
    print ('scraping page ' + str(page))
    soup = BeautifulSoup(data.text,"html.parser")
    for liste in soup.find_all('li',{'class':'clearfix'}):
        doc_details = []
        url_doc = liste.find('a').get('href')
        for a in liste.find_all('a'):
            if a.has_attr('name'):
                doc_details.append(a['name'])   
        data2 = requests.get(url_doc)       
        soup = BeautifulSoup(data2.text,"html.parser")
        a_tel = soup.find('div',{'class':'contact_doc add_comment'}).a              
        tel_tag=a_tel['onclick']
        tel = tel_tag[tel_tag.find("$(this).html("):tel_tag.find(");")].lstrip("$(this).html(") 
        doc_details.append(tel)         
    f.writerow(doc_details)

    page += 1
print("--- %s seconds ---" % (time.time() - start_time))

【问题讨论】:

  • 你在哪一行得到这个?也许您可以使用堆栈跟踪发布整个错误消息。
  • soup.find('div',{'class':'contact_doc add_comment'}) 没有找到任何东西,返回None,所以.a 失败。
  • @deceze 奇怪的是程序停在一个随机页面上,我已经在那个页面上检查过那个 div 是否存在。所以我想我需要实现一个重试的函数获取该 url 并再次解析它,直到找到 div。你能帮我解决我的第二个错误吗?

标签: python python-3.x web-scraping beautifulsoup


【解决方案1】:

你的错误在这里

   a_tel = soup.find('div',{'class':'contact_doc add_comment'}).a

soup.find 显然没有找到 div 与所寻求的类。返回值为None,根据定义,它没有属性。

您应该检查并决定是在循环中进一步查询continue 还是退出。例如:

   div_contact = soup.find('div',{'class':'contact_doc add_comment'})
   if div_contact is None:
       continue

   a_tel = div_contact.a

您也可以尝试使用 try .. except 块来覆盖更多情况(例如 div 实际上没有您所期望的)

   div_contact = soup.find('div',{'class':'contact_doc add_comment'})
   try:
       a_tel = div_contact.a
   except AttributeError:
       continue

理论上更 Pythonic。无论如何都是你的选择。

持续不断的错误检查是程序的一部分。

【讨论】:

  • 奇怪的是程序停在一个随机页面上,我已经在那个页面上检查过那个 div 是否存在。所以我想我需要实现一个函数来重试获取它url 并再次解析它,直到找到 div。你能帮我解决我的第二个错误吗?
  • 您可能会遇到同样的错误。即使在您看来它是具有相同类的 same div ...显然不是,这意味着您必须考虑额外的情况。
  • 关于编码...您必须决定如何处理该错误,但您可以查看write 的其他答案,它涵盖了使用write 时的Unicode 编码: *.com/questions/22392377/…
  • 关于编码我已经通过添加到 csv.writer encoding='utf-8'
【解决方案2】:
resp_find = soup.find('div',{'class':'contact_doc add_comment'})
if resp_find is not None:
    a_tel = resp_find.a

你可以查询soup.find()的response是否是NoneType对象,如果不是你可以应用.a

或者你确保 soup.find() 方法永远不会返回一个 NoneType 对象,所以你必须调查为什么这个方法返回一个 NoneType 对象

【讨论】:

  • 奇怪的是程序停在一个随机页面上,我已经在那个页面上检查过那个 div 是否存在。所以我想我需要实现一个函数来重试获取它url 并再次解析它,直到找到 div。你能帮我解决我的第二个错误吗?