Python-索引错误-列表索引超出范围

时间:2019-12-18 11:40:10

标签: python-3.x beautifulsoup

我正在解析来自网站的数据,但出现错误“ IndexError:列表索引超出范围”。但是,在调试时,我得到了所有值。以前,它完全可以正常工作,但是突然不明白为什么我会收到此错误。

@GET
@Path("connect")
@Produces(MediaType.SERVER_SENT_EVENTS)
public void subscribe(@Context SseEventSink sseEventSink, @Context Sse sse,
                      @HeaderParam(HttpHeaders.LAST_EVENT_ID_HEADER) @DefaultValue("-1") int lastReceivedId) {
...

while(true){

...

OutboundSseEvent sseEvent = sse.newEventBuilder()
        .comment("some comment")
        .name("some name")
        .id("somem id")
        .mediaType(MediaType.TEXT_PLAIN_TYPE)
        .data("some data")
        .reconnectDelay(30)
        .build();
CompletionStage<?> cs = sseEventSink.send(sseEvent);
cs.ifPresent(x -> {
    x.whenComplete((serverSideEvent, serverSideThrowable) -> {
        if (serverSideThrowable == null) {
            //ok
        } else {
            //error
        }
    });
});
}
  

IndexError:列表索引超出范围

这是我的代码。

str2 = cols[1].text.strip()

这些是调试时的值:

import requests
import DivisionModel
from bs4 import BeautifulSoup
from time import sleep


class DivisionParser:

    def __init__(self, zoneName, zoneUrl):
        self.zoneName = zoneName
        self.zoneUrl = zoneUrl

    def getDivision(self):

        response = requests.get(self.zoneUrl)
        soup = BeautifulSoup(response.content, 'html5lib')
        table = soup.findAll('table', id='mytable')
        rows = table[0].findAll('tr')

        division = []
        for row in rows:
            if row.text.find('T No.') == -1:
                cols = row.findAll('td')

                str1 = cols[0].text.strip()
                str2 = cols[1].text.strip()
                str3 = cols[2].text.strip()
                strurl = cols[2].findAll('a')[0].get('href')
                str4 = cols[3].text.strip()
                str5 = cols[4].text.strip()
                str6 = cols[5].text.strip()
                str7 = cols[6].text.strip()

                divisionModel = DivisionModel.DivisionModel(self.zoneName, str2, str3, strurl, str4, str5, str6, str7)
                division.append(divisionModel)
        return division

2 个答案:

答案 0 :(得分:0)

通常,来自寒冷和敌对的外部世界的任何东西都是完全不可靠的。在这里:

    response = requests.get(self.zoneUrl)
    soup = BeautifulSoup(response.content, 'html5lib')

您似乎遭受了可怕的幻想,那就是响应将永远是您所期望的。提示:不会。 保证,有时响应会有所不同-可能是该站点已关闭,或者因为他们不希望您剪贴数据而决定将您的IP列入黑名单。

IOW,您真的想检查响应的状态码和响应内容。实际上,您希望为任何事情做好准备-FWIW,因为您没有specify a timeout,所以您的代码可能会永远冻结,一直在等待响应

所以实际上您想要的是

try:
    response = requests.get(yoururl, timeout=some_appropriate_value)
    # cf requests doc
    response.raise_for_status() 

# cf requests doc
except requests.exceptions.RequestException as e
    # nothing else you can do here - depending on
    # the context (script ? library code ?), 
    # you either want to re-raise the exception
    # raise your own exception or well, just
    # show the error message and exit. 
    # Only you can decide what's the appropriate course
    print("couldn't fetch {}: {}".format(yoururl, e))
    return

 if not response.headers['content-type'].startswith("text/html"):
     # idem - not what you expected, and you can't do much
     # except mentionning the fact to the caller one way
     # or another. Here I just print the error and return
     # but if this is library code you want to raise an exception
     # instead
     print("{} returned non text/html content {}".format(yoururl, response.headers['content-type'])) 
     print("response content:\n\n{}\n".format(response.text))
     return

 # etc...

request有一些相当详尽的文档,我建议您阅读的内容比快速入门更多,以正确学习和使用它。这只是工作的一半-即使您确实得到200条响应,没有重定向和正确的内容类型,也不意味着标记就是您所期望的,因此在这里,您必须再次检查从BeautifulSoup获得的内容-例如:

table = soup.findAll('table', id='mytable')
rows = table[0].findAll('tr')

绝对没有任何理由保证标记包​​含具有匹配ID的任何表(也没有所有FWIW的任何表),因此您必须事先检查或处理异常:

table = soup.findAll('table', id='mytable')
if not tables:
    # oops, no matching tables ?
    print("no table 'mytable' found in markup")
    print("markup:\n{}\n".format(response.text))
    return
rows = table[0].findAll('tr')
# idem, the table might be empty, etc etc

编程的有趣之处之一是处理标称情况通常很简单-但是您必须处理所有可能的极端情况,这通常需要比标称情况更多或更多的代码;-)< / p>

答案 1 :(得分:0)

当我通过连续检查T号从网站中解析数据并在td中获取所有值时,网站开发人员在某td行中输入了“ No Result”,因此这就是为什么在运行时我的循环无法运行的原因获取值并通过“列表索引超出范围错误”。

非常感谢大家的帮助。

DivisionParser类:

def __init__(self, zoneName, zoneUrl):
    self.zoneName = zoneName
    self.zoneUrl = zoneUrl

def getDivision(self):
    global rows
    try:
        response = requests.get(self.zoneUrl)
        soup = BeautifulSoup(response.content, 'html5lib')
        table = soup.findAll('table', id='mytable')
        rows = table[0].findAll('tr')
    except IndexError:
            sleep(2)

    division = []
    for row in rows:
        if row.text.find('T No.') == -1:
            try:
                cols = row.findAll('td')

                str1 = cols[0].text.strip()
                str2 = cols[1].text.strip()
                str3 = cols[2].text.strip()
                strurl = cols[2].findAll('a')[0].get('href')
                str4 = cols[3].text.strip()
                str5 = cols[4].text.strip()
                str6 = cols[5].text.strip()
                str7 = cols[6].text.strip()
                divisionModel = DivisionModel.DivisionModel(self.zoneName, str2, str3, strurl, str4, str5, str6,
                                                            str7)
                division.append(divisionModel)
            except IndexError:
                print("No Result")
    return division