为什么xpath提取内容的代码换一个位置行就报错:IndexError: list index out of range

原代码:

import requests
import time
from lxml import etree
import random
from datetime import datetime

# 请求头
headers = {'user-agent': ' '}
# 设置url
url = 'https://www.cbaigui.com/'
i = 1

while True:
    # 反馈信息
    response = requests.get(url, headers=headers)
    # 设置类型
    response.encoding = 'utf8'
    # 解析数据
    html = etree.HTML(response.text)
    # 提取名称列表、详情页面的url列表
    names = html.xpath('//*[@id="page"]/div/div[1]/div/article/div/h2//text()')
    # 去掉name列表中的空字符与换行符
    names = [i.strip() for i in names if i.strip()]
    # 详情页面的url列表
    detail_urls = html.xpath('//*[@id="page"]/div/div[1]/div/article/div/h2//@href')
    # 提取下一页url
    next_url = html.xpath('//*[@id="page"]/div/div[1]/div/nav/div/a[@class="page larger"][1]//@href')[0]
    # 遍历names,detail_url,获取页面url
    for name, detail_url in zip(names, detail_urls):
        # 反馈信息
        response = requests.get(detail_url, headers=headers)
        # 设置类型
        response.encoding = 'utf8'
        # 解析数据
        html = etree.HTML(response.text)
        # 提取描述内容
        description = html.xpath('//*[@id="page"]/div/div[1]/div[2]/article/div/p/text()')
        # 内容换行
        description = '\n'.join(description)
        # 写入文件
        with open(f'cbaigui{datetime.now().strftime("%Y%m%d")}.txt', 'a', encoding='utf8') as f:
            f.write(f'{i}{name}\n{description}\n\n')
            print(f'{i}{name} 抓取成功')
        i += 1
        # 休眠间隔
        time.sleep(random.randint(1, 3))
    url = next_url

提取下一页url 的代码在写入文件之前

    # 提取下一页url
    next_url = html.xpath('//*[@id="page"]/div/div[1]/div/nav/div/a[@class="page larger"][1]//@href')[0]

原代码存在 爬取最后一页时 运行到提取下一页url的代码会报错,导致最后一页无法写入文件
所以我想把提取下一页url放在写入文件之后,实现即使报错,最后一页也已经爬取完毕,如下:

import requests
import time
from lxml import etree
import random
from datetime import datetime

# 请求头
headers = {'user-agent': ' '}
# 设置url
url = 'https://www.cbaigui.com/'
i = 1

while True:
    # 反馈信息
    response = requests.get(url, headers=headers)
    # 设置类型
    response.encoding = 'utf8'
    # 解析数据
    html = etree.HTML(response.text)
    # 提取名称列表、详情页面的url列表
    names = html.xpath('//*[@id="page"]/div/div[1]/div/article/div/h2//text()')
    # 去掉name列表中的空字符与换行符
    names = [i.strip() for i in names if i.strip()]
    # 详情页面的url列表
    detail_urls = html.xpath('//*[@id="page"]/div/div[1]/div/article/div/h2//@href')
    # 遍历names,detail_url,获取页面url
    for name, detail_url in zip(names, detail_urls):
        # 反馈信息
        response = requests.get(detail_url, headers=headers)
        # 设置类型
        response.encoding = 'utf8'
        # 解析数据
        html = etree.HTML(response.text)
        # 提取描述内容
        description = html.xpath('//*[@id="page"]/div/div[1]/div[2]/article/div/p/text()')
        # 内容换行
        description = '\n'.join(description)
        # 写入文件
        with open(f'cbaigui{datetime.now().strftime("%Y%m%d")}.txt', 'a', encoding='utf8') as f:
            f.write(f'{i}{name}\n{description}\n\n')
            print(f'{i}{name} 抓取成功')
        i += 1
        # 休眠间隔
        time.sleep(random.randint(1, 3))
    # 提取下一页url
    next_url = html.xpath('//*[@id="page"]/div/div[1]/div/nav/div/a[@class="page larger"][1]//@href')[0]
    url = next_url

但是运行到 提取下一页url这一行就会报错:IndexError: list index out of range
IndexError: list index out of range通常有两种情况

一个可能是下标超出范围,
一个可能是list是空的,没有一个元素

但我调试不出具体原因

  您已经找到问题“元凶”了。报错就是下标溢出,由引用不存在的下标引发。


next_url = html.xpath('//*[@id="page"]/div/div[1]/div/nav/div/a[@class="page larger"][1]//@href')[0]

  如果您 next_url == [] 时一定触发“下标溢出”错误。我这熟悉您的代码,因为我没学爬虫。😂您是不是可以用 string.join() 来获取列表中的字符串,这样子就不会因空列表而引发“下标溢出”报错了。

  您可以去除语句末尾的下标引用 [] ,用 ''.join() ,用空字符连接列表内的所有字符串元素——


next_url = ''.join(html.xpath('//*[@id="page"]/div/div[1]/div/nav/div/a[@class="page larger"][1]//@href'))


next_url = html.xpath('//*[@id="page"]/div/div[1]/div/nav/div/a[@class="page larger"][1]//@href')
next_url = ''.join(next_url)

试试看。



import requests
from lxml import etree

headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
for j in range(1,194):
    res=requests.get(f'https://www.cbaigui.com/page{j}',headers=headers)
    html = etree.HTML(res.text)
    names = html.xpath('//*[@class="post-title"]/a//text()')
    href=html.xpath('//*[@class="post-title"]/a/@href')
    for i in range(len(names)):
        print(names[i])
        res=requests.get(href[i])
        html = etree.HTML(res.text)
        content = html.xpath('//*[@class="entry"]//text()')
        print(content)