【问题标题】:Beautiful soup, list index out of range美丽的汤,列表索引超出范围
【发布时间】:2019-10-20 18:05:43
【问题描述】:

我查看了站点 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()

【问题讨论】:

  • 再次检查 cols 是什么。显然它没有 4 个元素。
  • 它有 4 个元素
  • 不能,否则不会导致该错误。确保您尝试获取的数据不在外部列表或字典等其他结构中。

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


【解决方案1】:

您正在循环期间覆盖colscols 的最后一个长度为零,因此您的错误。

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 值。这可能不适合您的确切用例,因为我不确定您想要的结果是什么。如果您说明所需的输出,我会相应地更新。


编辑:

玩家姓名

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 - 该问答中的其他解决方案)

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()

【讨论】:

  • 代码没有输出答案 ;(。我想为网站中的每个答案获取 PlayerName。
  • 请您提供应该出现的这些玩家名称的示例。
  • 'namePlayer': VANTY3 'namePlayer': KK#キング 'namePlayer': 回忆。等等所有回答这个话题的人的昵称
  • 非常感谢!它有效,我得到了我想要的。但是我不明白他是怎么对这些名字排序的,是随机的吗?
  • 列表将按正确的顺序排列。集合没有顺序(唯一的)。您可以改为在循环中进行重复数据删除。
【解决方案2】:

听起来您正在提供一个不存在列表元素的索引。记住索引从 0 开始。例如:0,1,2,3。所以如果我要求元素 10,我会得到一个索引错误。

【讨论】:

    【解决方案3】:

    为什么使用 for 循环来查找所有 div 标签:

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

    通过使用它,你得到了你想要的所有标签

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

    因此,只需使用此代码更改您的代码,您就会得到答案。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-30
      • 1970-01-01
      • 2020-07-17
      • 1970-01-01
      • 2018-12-16
      • 2011-06-14
      • 2016-06-04
      相关资源
      最近更新 更多