おそらく、通常のspyderの記述ではIndexErrorは発生しないでしょう。私がscrapyで最初にindexErrorに出会ったのは、spyderの記述を色々と試していたときでした。
見よう見まねで、spyderをいじっているときに、「こういうふうにも抽出箇所を指定できそうだな」と思って使っていたのが以下のような記述です。
yield{ 'spam': response.css('ham.eggs')[1].extract_first() }
とした場合に、responseオブジェクトはlist型のオブジェクトなので、末尾に[1]を付けて抽出箇所を指定できるだろうと。
scrapy shellで試してみたところ、ちゃんとうまくいきました。
ところがこれがいけなかった。
指定した箇所が存在しない場合、scrapyはnoneを返すが、オブジェクトのリストに[1]を付けているので、リストに対してindexを行ってから.extract_first()メソッドを実行するような挙動になる。その場合、もし指定した箇所が存在しない場合は、リストに対するindexがErrorを返す。noneではなくErrorだ。
だから、通常通りに抽出箇所を指定すればErrorではなくnoneを返してscrapyが続行するのに対して、わざわざ[1]などを付けてlist型にindexを行うように記述するとpythonがErrorを返してscrapyが止まってしまう。
scrapyがIndexError: list index out of rangeを吐いて止まってしまわないように、spyderではlist型のindexを記述するのはやめよう。と思いました。
IndexError: list index out of range の意味
以下のURLを参考にしてください。
What does list index out of range mean?