【问题标题】:Python : Cannot access list element even though it existsPython:即使存在也无法访问列表元素
【发布时间】:2016-11-05 12:06:40
【问题描述】:

我正在尝试编写代码,以使用 Python 及其 urllib2BeautifulSoup 库从网站中提取数据。

我尝试遍历所需表的行,然后将“td”中指定的每一行中的数据存储到列表变量row_data中。事件虽然我可以打印整个列表,但我无法访问特定索引处的列表,并且解释器抛出“列表索引超出范围”错误。这是我的代码和输出。

import urllib2
from bs4 import BeautifulSoup

link = 'http://www.babycenter.in/a25008319/most-popular-indian-baby-names-of-2013'
page = urllib2.urlopen(link)
soup = BeautifulSoup(page)
right_table = soup.find('table', class_= 'contentTable colborders')
name=[]
meaning=[]
alternate=[]

for row in right_table.find_all("tr"):
  row_datas = row.find_all("td")
  print row_datas
  print row_datas[0]

输出:

[]Traceback (most recent call last):
  File "C:\Users\forcehandler\Documents\python\data_scrape.py", line 41, in <module>

print row_datas[0]
IndexError: list index out of range
[Finished in 1.6s]

我尝试了类似的代码来标记任何明显的错误,但无济于事。 代码:

i = [range(y,10) for y in range(5)]
for j in i:
  print j
  print j[0]

输出:

[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
0
[1, 2, 3, 4, 5, 6, 7, 8, 9]
1
[2, 3, 4, 5, 6, 7, 8, 9]
2
[3, 4, 5, 6, 7, 8, 9]
3
[4, 5, 6, 7, 8, 9]
4

我是编程新手,在其他任何地方都找不到帮助。提前致谢!

编辑:Traceback 之前的“[]”可能在复制粘贴时意外滑入输出。感谢您提供有用的答案/建议。

解决方案:我在使用数据之前没有检查数据的完整性。事实证明,第一行仅包含“th”值而没有“td”值,因此出现错误。

经验教训:始终在将数据投入使用之前对其进行测试。

附带说明:这是我在 StackOverflow 上的第一个问题,如此快速、高质量和有用的回答让我不知所措。

【问题讨论】:

  • print row_datas 是否随时显示空列表?
  • 您的print row_datas 行在该回溯之前打印出[](您有[]Traceback,而不是Traceback,您可能想弄清楚为什么您似乎没有打印换行符)。列表为空,索引 0 处没有元素。
  • 查看该表,52 行中只有 50 行包含 td 元素;有两行带有th 标题元素。

标签: python beautifulsoup urllib2


【解决方案1】:

您的输出显示至少有一行是

[]Traceback (most recent call last):
^^

[] 是一个空列表,输出是由您的 print row_datas 行生成的。通常我希望在它和Traceback 之间有一个换行符;也许你没有正确复制你的输出,或者你有一个使用大小缓冲区而不是行缓冲的控制台,导致它混合了标准输出和标准错误。

这是因为这些行中的第一行包含 th 标题单元格:

>>> rows = soup.select('table.contentTable tr')
>>> rows[0].find('td') is None
True
>>> rows[0].find_all('th')
[<th width="20%">Name</th>, <th>Meaning</th>, <th>Popular <br/>\nalternate spellings</th>]

还有另外一个这样的行,所以你必须防御性地编码:

>>> rows[26]
<tr><th width="20%">Name</th><th>Meaning</th><th>Popular <br/>\nalternate spellings</th></tr>

您可以只测试是否有任何带有if 语句的元素:

if row_datas:
    print row_datas[0]

提取所有名称、含义和替代拼写的代码非常简单:

for row in soup.select('table.contentTable tr'):
    cells = row.find_all('td')
    if not cells:
        continue
    name_link = cells[0].find('a')
    name, link = name_link.get_text(strip=True), name_link.get('href')
    meaning, alt = (cell.get_text(strip=True) for cell in cells[1:])
    print '{}: {} ({})'.format(name, meaning, alt)

【讨论】:

  • 感谢您指出错误。忽略这一点真是太愚蠢了。感谢您提供更简洁的代码供我使用!
【解决方案2】:

您收到此错误是因为您的列表没有元素,row.find_all("td") 找不到任何东西,您必须检查您的 html 结构或使用 select 方法。

select() 返回通过 CSSS 选择器选择的所有元素,它非常强大,您的代码将是这样的:

 row_datas = soup.select("td") #Note that select() is method of a BeautifulSoup Object .
  print row_datas
  print row_datas[0]

【讨论】:

  • select() 似乎比find() 函数好用得多。感谢您的回答!
猜你喜欢
  • 1970-01-01
  • 2023-04-10
  • 1970-01-01
  • 1970-01-01
  • 2018-10-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多