删除网页并将信息存储在列表中时出现索引外错误



我目前在数据科学训练营,目前我在课程中处于领先地位,所以我想借此机会应用我在第一个项目中学到的一些技能。我正在从票房Mojo中抓取电影信息,并希望最终将所有这些信息编译成熊猫数据帧。到目前为止,我有一个分页功能,可以收集各个电影的所有链接:

def pagination_func(req_url):
    soup = bs(req_url.content, 'lxml')
    
    table = soup.find('table')
    links = [a['href'] for a in table.find_all('a', href=True)]
    pagination_list = []
    substring = '/release'
    for link in links:
        if substring in link:
            pagination_list.append(link)
            
    return pagination_list

我有点懒洋洋地实现了一个硬连接的URL,通过这个函数来检索请求的数据:

years = ['2010', '2011', '2012', '2013', '2014', '2015', '2016', '2017', '2018', '2019']
link_list_by_year = []
for count, year in tqdm(enumerate(years)):
    pagination_url = 'https://www.boxofficemojo.com/year/{}/?grossesOption=calendarGrosses'.format(year)
    pagination = requests.get(pagination_url)
    link_list_by_year.append(pagination_func(pagination))

这将给我不完整的URL,然后我用这个for循环将其转换为完整的URL:

complete_links = []
for link in link_list_by_year:
    for url in link:
        complete_links.append('https://www.boxofficemojo.com{}'.format(url))

然后,我使用lxml库从页面中检索我想要的具有以下功能的元素:

def scrape_page(req_page):
    tree = html.fromstring(req_page.content)
    
    title.append(tree.xpath('//*[@id="a-page"]/main/div/div[1]/div[1]/div/div/div[2]/h1/text()')[0])
    
    domestic.append(tree.xpath(
        '//*[@id="a-page"]/main/div/div[3]/div[1]/div/div[1]/span[2]/span/text()')[0].replace('$','').replace(',',''))
    
    international.append(tree.xpath(
        '//*[@id="a-page"]/main/div/div[3]/div[1]/div/div[2]/span[2]/a/span/text()')[0].replace('$','').replace(',',''))
    
    worldwide.append(tree.xpath(
        '//*[@id="a-page"]/main/div/div[3]/div[1]/div/div[3]/span[2]/a/span/text()')[0].replace('$','').replace(',',''))
    
    opening.append(tree.xpath(
        '//*[@id="a-page"]/main/div/div[3]/div[4]/div[2]/span[2]/span/text()')[0].replace('$','').replace(',',''))
    
    opening_theatres.append(tree.xpath(
        '/html/body/div[1]/main/div/div[3]/div[4]/div[2]/span[2]/text()')[0].replace('n', '').split()[0])
    
    MPAA.append(tree.xpath('//*[@id="a-page"]/main/div/div[3]/div[4]/div[4]/span[2]/text()')[0])
    
    run_time.append(tree.xpath('//*[@id="a-page"]/main/div/div[3]/div[4]/div[5]/span[2]/text()')[0])
    
    genres.append(tree.xpath('//*[@id="a-page"]/main/div/div[3]/div[4]/div[6]/span[2]/text()')[0].replace('n','').split())
    
    run_time.append(tree.xpath('//*[@id="a-page"]/main/div/div[3]/div[4]/div[5]/span[2]/text()')[0])

我继续初始化这些列表,为了文本墙,我将不发布这些列表,它们都只是标准的var = []

最后,我有一个for循环,它将迭代我的已完成链接列表:

for link in tqdm(complete_links[:200]):
    movie = requests.get(link)
    scrape_page(movie)

所以这一切都很基本,也不是很优化,但它帮助我理解了很多关于Python基本性质的东西。不幸的是,当我在抓取页面大约一分钟后运行循环来抓取页面时,它会抛出一个IndexError: list index out of range,并给出以下调试回溯(或与scrape_page函数中的操作类似的性质(:

IndexError                                Traceback (most recent call last)
<ipython-input-381-739b3dc267d8> in <module>
      4 for link in tqdm(test_links[:200]):
      5     movie = requests.get(link)
----> 6     scrape_page(movie)
      7 
      8 
<ipython-input-378-7c13bea848f6> in scrape_page(req_page)
     14 
     15     opening.append(tree.xpath(
---> 16         '//*[@id="a-page"]/main/div/div[3]/div[4]/div[2]/span[2]/span/text()')[0].replace('$','').replace(',',''))
     17 
     18     opening_theatres.append(tree.xpath(
IndexError: list index out of range

我认为出了问题的是,它挂在的特定页面要么缺少特定元素,要么标记不同,要么有某种奇怪之处。我一直在寻找一种错误处理方法,但我找不到一种与我所寻找的内容相关的方法。老实说,在2个小时的大部分时间里,我一直在思考这个问题,(在我有限的知识范围内(我已经做了所有的事情,但在每一页上都用手搜索了一些问题。

在尝试将结果附加到列表之前,请检查xpath()是否返回了任何内容。

    openings = tree.xpath('//*[@id="a-page"]/main/div/div[3]/div[4]/div[2]/span[2]/span/text()')
    if openings:
        opening.append(openings[0].replace('$','').replace(',',''))

由于您可能应该对所有列表都这样做,因此您可能希望将模式提取到一个函数中:

def append_xpath(tree, list, path):
    matches = tree.xpath(path)
    if matches:
        list.append(matches[0].replace('$','').replace(',',''))

然后你会这样使用它:

append_xpath(tree, openings, '//*[@id="a-page"]/main/div/div[3]/div[4]/div[2]/span[2]/span/text()')
append_xpath(tree, domestic, '//*[@id="a-page"]/main/div/div[3]/div[1]/div/div[1]/span[2]/span/text()')
...

最新更新