抓取网页并将信息存储在列表中时出现索引错误

Out of Index Error while Scraping Web Pages and storing information in a list

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

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))

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

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 并给出以下调试回溯(或与 [= 中的操作有关的类似性质之一) 21=]函数):

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()')
...