2017-10-07 1 views
0

Je reçois une erreur comme le titre.AttributeError: l'objet 'NoneType' n'a pas d'attribut 'div'

Traceback (most recent call last): 
    File "C:/2.py", line 40, in <module> 
reviews.append(reviews_info(div)) 
    File "C:/2.py", line 21, in reviews_info 
    review_text = div.find("div", "review-content").div.text 
AttributeError: 'NoneType' object has no attribute 'div' 

Je suppose que j'ai probablement entré le mauvais élément.

Je n'ai pas écrit le code à partir de zéro. J'ai appliqué au code qui explorait précédemment d'autres sites.

Comment puis-je changer l'élément et le tourner? Je pense que j'ai bien écrit. Mais il y a une erreur.

ps J'ai peur qu'il y ait un commentaire pour utiliser api. Mais c'est la façon de l'utiliser car elle est limitée.

import sys 
from bs4 import BeautifulSoup 
import urllib.request 
import requests 
from urllib.parse import quote 

import os 
import xlwt 

import re 
import time 
import random 
import re, requests, csv 
from bs4 import BeautifulSoup 
from time import sleep 

# CMD chcp 65001 


def reviews_info(div): 
    review_text = div.find("div", "review-content").div.text 
    review_stars = div.find("div", "i-stars i-stars--regular-1 rating-large").a.text 
    return { 
     "review_text" : review_text, 
     "review_stars" : review_stars, 
    } 

base_url = "https://www.yelp.com/biz/founding-farmers-d-c-washington-2?start=" 
reviews = [] 
NUM_PAGES = 36 

for page_num in range(1, NUM_PAGES + 20): 
    print("souping page", page_num, ",", len(reviews), "data") 
    url = base_url + str(page_num) 
    soup = BeautifulSoup(requests.get(url).text, 'lxml') 

    for div in soup('div', 'review-content'): 
     reviews.append(reviews_info(div)) 
    sleep(5)############################################# 
    # Save dict data 
keys = reviews[0].keys() 
with open('testtest.csv', 'w', encoding="utf-8") as f: 
    dict_writer = csv.DictWriter(f, delimiter=',', lineterminator='\n', fieldnames=keys) 
    dict_writer.writeheader() 
    dict_writer.writerows(reviews) 
+0

La façon dont vous avez décrit votre liste de raclage et de choses à faire est complètement vague. Il serait préférable que vous spécifiez les champs que vous souhaitez analyser à partir du lien fourni dans votre grattoir. – SIM

Répondre

0

Dans votre boucle, vous êtes déjà passer à la div reviews_info qui a un attribut de classe de « contrôle-contenu ». Donc, vous êtes probablement mieux d'enlever la partie .find("div", "review-content"). Cela pourrait être une cause de l'erreur.

Apparemment, vous avez besoin de la date de révision et des étoiles.

Au lieu d'utiliser div.div.text pour extraire la date, vous pouvez utiliser la balise span qui contient la date, comme celui-ci:

review_date = div.span.next_element.strip() 

L'expression que vous utilisez pour extraire les évaluations soulèvera une autre erreur.

Les «i-stars i-stars - regular-1 rating-large» s'appliquent pour une classification 1 étoile. Donc, une cote de 4 étoiles aurait un div avec class="i-stars i-stars--regular-4 rating-large", et ainsi de suite.

Ainsi, vous pouvez utiliser regex pour filtrer les div contenant la note:

review_stars = div.find('div', {'class': re.compile(r'i-stars')}).img['alt'] 

Mettre ces deux parties ensemble, les deux lignes qui doivent être modifiés dans votre fonction reviews_info sont:

review_date = div.span.next_element.strip() 
review_stars = div.find('div', {'class': re.compile(r'i-stars')}).img['alt'] 

Faites ces changements et vous devriez être prêt à partir.

Extra info:

La raison pour laquelle je n'ai pas utilisé div.span.text.strip() pour extraire le texte est que si l'examen a été mis à jour après sa publication, l'étiquette span contenait ce détail, aussi. Et en utilisant span.text extrait également cette information. Par conséquent, j'ai choisi next_element.

Clause de non-responsabilité: Je l'ai testé sur la troisième page seulement, et cela a fonctionné pour moi. Je ne suis pas sûr que d'autres pages fonctionneront sans problèmes.