Мой код обрабатывает список словарей, как строка, typeerror: TypeError: строковые индексы должны быть целыми числами - PullRequest
0 голосов
/ 21 января 2019

поэтому я работаю с API Reddit, по некоторым причинам, не относящимся к делу, я хочу работать без использования оболочки Reddit для этого сценария.Код на самом деле очень прост, он извлекает комментарии и ответы 1 уровня из определенного поста внутри subreddit.

Это код функции,

def getcommentsforpost(subredditname,postid,):

    #here we make the request to reddit, and create a python dictionary   
    #from the resulting json code


    reditpath = '/r/' + subredditname + '/comments/' + postid
    redditusual = 'https://www.reddit.com'
    parameters = '.json?'
    totalpath = redditusual + reditpath + parameters
    p = requests.get(totalpath, headers = {'User-agent' : 'Chrome'})
    result = p.json()

    #we are going to be looping a lot through dictionaries, to extract
    # the comments and their replies, thus, a list where we will insert  
    # them.
    totallist = [] 

    # the result object is a list with two dictionaries, one with info 
    #on the post, and the second one with all the info regarding the 
    #comments and their respective replies, because of this, we first 
    # process the posts info located in result[0]


    a = result[0]["data"]["children"][0]["data"]
    abody = a["selftext"]
    aauthor = a["author"]
    ascore = a["score"]
    adictionary = {"commentauthor" : aauthor , "comment" : abody , "Type" : "Post",
                       "commentscore" : ascore}

    totallist.append(adictionary)




    # and now, we start processing the comments, located in result[1]

    for i in result[1]["data"]["children"]:

        ibody = i["data"]["body"]
        iauthor = i["data"]["author"]
        iscore = i["data"]["score"]



        idictionary = {"commentauthor" : iauthor , "comment" : ibody , "Type" : "post_comment",
                       "commentscore" : iscore}

        totallist.append(idictionary)

       # to clarify, until here, the code works perfectly. No problem 
       # whatsoever, its exactly in the following section where  the 
       #error happens. 

       # we create a new object, called replylist, 
        #that contains a  list of dictionaries in every interaction of 
        #the loop. 

        replylists =  i["data"]["replies"]["data"]["children"]

        # we are going to loop through them, in every comment we extract


        for j in replylists:
            jauthor = j["data"]["author"]
            jbody = j["data"]["body"]
            jscore = j["data"]["score"]


            jdictionary = {"commentauthor" : jauthor , "comment" : jbody , "Type" : "comment_reply" , 
                           "commentscore" : jscore } 
            totallist.append(jdictionary)

        # just like we did with the post info and the normal comments,
         # we extract and put it in totallist. 



        finaldf = pd.DataFrame(totallist)



    return(finaldf)

getcommentsforpost("Python","a7zss0")

, но во время выполнения этого цикла для ответов код завершается ошибкой.Он возвращает эту ошибку «строковые индексы должны быть целыми числами», сигнализируя об ошибке переменным ответным спискам, но когда я выполняю код вне цикла, как это

result[1]["data"]["children"][4]["data"]["replies"]["data"]["children"][0]

, он работает отлично, он должен быть таким жеэффект.Я считаю, что он рассматривает списки ответов как строку, а не список (который является его классом)

Вещи, которые я пробовал:

Я пытался убедиться, что класс списков ответов представляет собой список сФункция type (), она доказывает, что возвращает «список», но только для 5 взаимодействий цикла, затем происходит сбой с той же ошибкой.

Я попытался сделать цикл списка с for ja in range(0,len(replylists)), а затем создатьj переменная как replylists[ja].Она выдала ту же ошибку.

Я отлаживал это два часа, без этого фрагмента кода функция работает отлично (конечно, она не возвращает ответы в конечном кадре данных, но работает),Почему это происходит?replylists - это список словарей, а не строка, но она выдает эту странную ошибку.

Вот документация reddit для функции, которую мы используем: https://www.reddit.com/dev/api#GET_comments_{article}

Библиотеки для импорта: запросы, панды как pd, json

Повторяю, рекомендую оберткуне решение, я хочу работать с json и отдыхать.

Работаем над этим: 'Python версия 3.6.5 | Anaconda версия 5.2.0, ноутбук jupyter 5.5.0'

Заранее спасибо.Надеюсь, это будет интересно, я буду продолжать работать отсюда.

Ответы [ 2 ]

0 голосов
/ 22 января 2019

Вот как я решил это, создал оператор if, чтобы проверить, является ли ["data"] ["replies"] словарем, выполняя код в этом случае и продолжая цикл, если это не так.

Вот как это выглядит, еще раз спасибо Адитье и Гойо:

def getcommentsforpost(subredditname,postid,):
reditpath = '/r/' + subredditname + '/comments/' + postid
redditusual = 'https://www.reddit.com'
parameters = '.json?'
totalpath = redditusual + reditpath + parameters
p = requests.get(totalpath, headers = {'User-agent' : 'Chrome'})
result = p.json()

totallist = []

# the result object is a list with two dictionaries, one with info on the post, and the second one
# with all the info regarding the comments and their respective replies 
a = result[0]["data"]["children"][0]["data"]
abody = a["selftext"]
aauthor = a["author"]
ascore = a["score"]
adictionary = {"commentauthor" : aauthor , "comment" : abody , "Type" : "Post",
                   "commentscore" : ascore}

totallist.append(adictionary)


for i in result[1]["data"]["children"]:

    ibody = i["data"]["body"]
    iauthor = i["data"]["author"]
    iscore = i["data"]["score"]


    idictionary = {"commentauthor" : iauthor , "comment" : ibody , "Type" : "post_comment",
                   "commentscore" : iscore}

    totallist.append(idictionary)


    if isinstance(i["data"]["replies"],dict) :

        replylists =  i["data"]["replies"]["data"]["children"]

        for j in replylists:
            jauthor = j["data"]["author"]
            jbody = j["data"]["body"]
            jscore = j["data"]["score"]
            jdictionary = {"commentauthor" : jauthor , "comment" : jbody , "Type" : "comment_reply" , 
                       "commentscore" : jscore } 

            totallist.append(jdictionary)



    elif  type(i["data"]["replies"]) == 'str':
        continue



finaldf = pd.DataFrame(totallist)



return(finaldf)
0 голосов
/ 22 января 2019

Я немного покопался и скопировал ваш код в локальную среду и провел некоторую отладку, в первую очередь это:

try:
    replylists =  i["data"]["replies"]["data"]["children"]
except:
    for point in i['data']:
        print(point)
    exit()

Посредством этого я увидел, что на самом деле i["data"] имеет значения (на самом деле 57 из них), и одно из 57 включает replies, однако я кое-что просмотрел и обнаружил, что содержание ответов пусто:

'replies': '' - это то, что я вижу, когда непосредственно распечатываю i для неработающих значений.

Однако вся надежда не потеряна: вы просто забыли проигнорировать итерации, где содержимое ответов пустое (''), поскольку я также проверил проверку, чтобы узнать, сколько ваших итераций действительно провалилось, а некоторые работал, а некоторые не удалось (из-за ранее упомянутых рассуждений).

В связи с этим я даю вам совет использовать try и except при возникновении ошибки, подобной этой, для отладки (это полезный навык), а также, а также по теме вашего вопроса, выяснить, что вы хотите нравится делать, когда содержимое ответов пусто.

Я желаю вам всего наилучшего и надеюсь, что это помогло.

...