Красивый суп, список индекса вне диапазона - PullRequest
0 голосов
/ 20 октября 2019

Я посмотрел на источник html сайта и нашел то, что мне нужно для namePlayer, это был 4 столбца и тег 'a'. И я попытался найти его в answers.append с 'namePlayer': cols[3].a.text

Но когда я компилирую это, я получаю IndexError. Затем я пытаюсь изменить индекс на 2,3,4,5, но ничего.

Проблема: почему я получаю IndexError: список индекса выходит за пределы диапазона, когда все в порядке (я думаю: D)

источник:

#!/usr/bin/env python3

import re
import urllib.request
from bs4 import BeautifulSoup

class AppURLopener(urllib.request.FancyURLopener):
    version = "Mozilla/5.0"


def get_html(url):
    opener = AppURLopener()
    response = opener.open(url)
    return response.read()

def parse(html):
    soup = BeautifulSoup(html)
    table = soup.find(id='answers')

    answers = []

    for row in table.find_all('div')[16:]:
        cols = row.find_all('div')

    answers.append({
        'namePlayer': cols[3].a.text
    })


    for answer in answers:
        print(answers)


def main():
    parse(get_html('http://jaze.ru/forum/topic?id=50&page=1'))

if __name__ == '__main__':
    main()

Ответы [ 3 ]

0 голосов
/ 20 октября 2019

Вы перезаписываете cols во время цикла. Последняя длина cols равна нулю, следовательно, ваша ошибка.

for row in table.find_all('div')[16:]:
    cols = row.find_all('div')
    print(len(cols))

Запустите приведенное выше, и вы увидите, что cols заканчивается на длине 0.

Это может также произойти в другом месте цикла, поэтому вы должны проверить длину и также решить, соответствует ли ваша логикануждается в обновлении. Кроме того, вам необходимо учитывать наличие дочернего тега a.

Таким образом, вы можете, например, сделать следующее (требуется bs4 4.7.1+):

answers = []

for row in table.find_all('div')[16:]:
    cols = row.find_all('div:has(>a)')
    if len(cols) >= 3:
         answers.append({
        'namePlayer': cols[3].a.text
    })

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


РЕДАКТИРОВАТЬ:

playerNames

from bs4 import BeautifulSoup as bs
import requests

r = requests.get('https://jaze.ru/forum/topic?id=50&page=1')
soup = bs(r.content, 'lxml')
answer_blocks = soup.select('[id^=answer_]')
names = [i.text.strip() for i in soup.select('[id^=answer_] .left-side a')]
unique_names = {i.text.strip() for i in soup.select('[id^=answer_] .left-side a')}

Вы можете сохранить порядок и дедублировать сOrderedDict (это @ Michael - другие решения в этом Q & A)

from bs4 import BeautifulSoup as bs
import requests
from collections import OrderedDict

r = requests.get('https://jaze.ru/forum/topic?id=50&page=1')
soup = bs(r.content, 'lxml')
answer_blocks = soup.select('[id^=answer_]')
names = [i.text.strip() for i in soup.select('[id^=answer_] .left-side a')]
unique_names = OrderedDict.fromkeys(names).keys()
0 голосов
/ 20 октября 2019

почему вы используете цикл для нахождения всех тегов div:

for row in table.find_all('div')[16:]:
        cols = row.find_all('div')

, используя это, вы получаете все нужные теги

cols = table.find_all('div')[16:]

, поэтому просто измените свой код с этим кодоми ты получил ответ.

0 голосов
/ 20 октября 2019

Звучит так, будто вы предоставляете индекс, для которого элемент списка не существует. Помните, что индекс начинается с 0. пример: 0,1,2,3. Поэтому, если я попрошу элемент 10, я получу ошибку индексации.

...