入门练习:利用标准API 获取电影海报图片的 url

获取数据练习:Wikipedia电影海报

背景

新近开始学习数据分析师课程,目前在数据获取阶段。这边记录下自己的课堂练习,也为后面复习留个底。

练习内容

如标题,利用维基百科标准的 url 格式,由电影标题生成对应的维基页面 url, 并批量访问下载电影海报。

已知条件:

通过 MediaWiki API 使用 wptools 访问维基百科页面数据,需要每部电影的维基百科页面标题,即网址中 en.wikipedia.org / wiki / 里最后一个斜杠之后的内容。测试中已经给出前 100 部电影的所有标题,我是直接拿来用的。
另外课程导师还贴心提示了下载代码技巧,避免走弯路:

import requests
from PIL import Image
from io import BytesIO
r = requests.get(url)
i = Image.open(BytesIO(r.content))

这样的做法好过用常规的文件打开、读取和写入方法(如下),这种有时候会破坏写入的文件。

import requests
r = requests.get(url)
with open(folder_name + '/' + filename, 'wb') as f:
    f.write(r.content)

练习解决方案

# 导入必须的工具包
import pandas as pd
import wptools
import os
import requests
from PIL import Image
from io import BytesIO
# 定义电影标题列表,用来生成 url
title_list = [
 'The_Wizard_of_Oz_(1939_film)',
 'Citizen_Kane',
 'The_Third_Man',
 'Get_Out_(film)',
 'Mad_Max:_Fury_Road'
]
# 准备好要用来存放下载图片的文件夹
folder_name = 'bestofrt_posters'
# 如果没有目录,创建目录
if not os.path.exists(folder_name):
    os.makedirs(folder_name)
# 字典列表可以逐个创建文件,随后转化为一个 DataFrame
df_list = []
image_errors = {}
for title in title_list:
    try:
        # 这个单元格较慢,所以输出排行时计算剩余时间
        ranking = title_list.index(title) + 1
        print(ranking)
        page = wptools.page(title, silent=True).get()
        # 这里是你的代码 (三行)
        images = page.data['image']
        # 第一个图片通常是海报
        first_image_url = images[0]['url']
        r = requests.get(first_image_url)
        # 下载电影海报图片
        i = Image.open(BytesIO(r.content))
        image_file_format = first_image_url.split('.')[-1]
        i.save(folder_name + "/" + str(ranking) + "_" + title + '.' + image_file_format)
        # 添加到字典列表中
        df_list.append({'ranking': int(ranking),
                        'title': title,
                        'poster_url': first_image_url})
    
    # 这不是抓住所有例外情况的最佳实践,但是适用于这一小段短小的程序脚本
    except Exception as e:
        print(str(ranking) + "_" + title + ": " + str(e))
        image_errors[str(ranking) + "_" + title] = images

完成上面代码要求后,读取并运行下面三个单元格,解释输出结果。

for key in image_errors.keys():
    print(key)

结果:

22_A_Hard_Day%27s_Night_(film)
64_Dr.Strangelove
72_Rosemary%27s_Baby
(film)
83_Hell_or_High_Water_(film)

# 检查无法识别的图片,并逐个下载
for rank_title, images in image_errors.items():
    if rank_title == '22_A_Hard_Day%27s_Night_(film)':
        url = 'https://upload.wikimedia.org/wikipedia/en/4/47/A_Hard_Days_night_movieposter.jpg'
    if rank_title == '64_Dr._Strangelove':
        url = 'https://upload.wikimedia.org/wikipedia/en/e/e6/Dr._Strangelove_poster.jpg'
    if rank_title == '72_Rosemary%27s_Baby_(film)':
        url = 'https://upload.wikimedia.org/wikipedia/en/e/ef/Rosemarys_baby_poster.jpg'
    if rank_title == '83_Hell_or_High_Water_(film)':
        url = 'https://upload.wikimedia.org/wikipedia/en/8/8f/Hell_or_High_Water_film_poster.png'
    title = rank_title[3:]
    df_list.append({'ranking': int(title_list.index(title) + 1),
                    'title': title,
                    'poster_url': url})
    r = requests.get(url)
    # 下载电影海报图片
    i = Image.open(BytesIO(r.content))
    image_file_format = url.split('.')[-1]
    i.save(folder_name + "/" + rank_title + '.' + image_file_format)
# 从字典列表中创建 DataFrame
df = pd.DataFrame(df_list, columns = ['ranking', 'title', 'poster_url'])
df = df.sort_values('ranking').reset_index(drop=True)
df

结果: df长这样
最后来一轮官方检查:

df_solution = pd.read_pickle('df_solution.pkl')
pd.testing.assert_frame_equal(df, df_solution)

然后我就得到了这么一个错误信息:
我得到的错误信息

总结

本课程重点:

  1. try … except …异常处理简单案例
try:
	# 执行代码,注意要写在缩进格式的代码块中
except Exception as e:
	# 释放错误动作代码,同上,注意写在代码块区域中
  1. API 使用练习:
import wptools
# 获取页面信息
page = wptools.page(<your_key_word>, silent=True).get()
# 获取页面信息中的图像信息
images = page.data['image']
  1. JSON 结构。JSON 对象在 python 中被读取为 Dictionary 数据格式。
    之前拿的 page 本身在 python 中式 wptools.page.WPToolsPage 对象,这个类型的对象不会被当成 Dictionary读取,每次要读就给我提示这个错误:

“如何将 WPToolsPage 转化为 JSON ”这一步我查了俩小时o(╥﹏╥)o
答案: page.data
没错,在 WPToolsPage 屁股后面加个 .data 然后 python 就能当做 JSON 读取了。

  1. 检验虽然未通过,但是我重新打印整个df自查的结果来看,获取结果至少是完整的。检验机制是用标准答案跟我的练习答案进行对比。然而标准答案失踪了╭(╯^╰)╮那我有什么办法……只好过一段时间再看下有没有更新吧。

  2. 存储。现在电影海报信息在df里面,不考虑共享,仅作为展示用,可以选择 flat file 方式存储。

df.to_csv('bestofrt_master.csv', index=False)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值