我目前在数据科学训练营,目前我在课程中处于领先地位,所以我想借此机会应用我在第一个项目中学到的一些技能。我正在从票房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()')
...