更多课程 选择中心


Python培训

400-111-8989

Python实战【第六节】拿来主义

  • 发布:Python培训
  • 来源:Crossin的编程教室
  • 时间:2019-03-22 15:43

欢迎大家来到Python自学教程实战篇,我们已经能让这个电影网站看起来更像一个网站了,而且用户可以在站内搜索自己喜欢的影片信息了,但是我们怎样才能获取更多的影片信息呢?一个一个一条一条去录入吗?那得到猴年马月?有没有什么简便的方法呢?

Python实战【第六节】拿来主义

我们没有必要也不可能自己去生产数量庞大的电影信息,互联网上的资源已足够满足我们的需求。(不过如果你要使用这些资源进行商业用途,请尊重内容来源方的版权。)

这个项目里,我将用豆瓣电影的 API 来获取内容。不要问我如何知道豆瓣有 API 可以做这样的事。我只是觉得它应该有,然后就去搜索引擎里搜索“豆瓣 api”,结果真的有。大概扫了下文档和示例,发现还挺好用的,于是就它了。

类似的情况还有之前的“查天气”系列课程,有人问是怎么知道获取天气的 API 地址,另外最初的地址现在已失效,如何更换新地址。对于这些,我也并不比各位了解更多,只是在需要的时候去网上搜索,发掘想要的答案。作为一名程序员,正确使用搜索引擎是最基本的技能。

现在许多内容型网站都将其数据开放了 API 供开发者使用,包括天气预报、电影、图书、地图、商户信息等等。对于没有 API 的网站,也可以通过直接抓取网页上的内容获得数据,也就是通常说的“爬虫”。API 和爬虫的区别在于,API 是内容提供方将信息整理好主动提供给你,数据有标准的格式,但使用时会受一定的限制;爬虫则是你直接从网页上的展现内容里去分析并提取你要的信息,一般来说是未经授权的。从实现上来说,API会比爬虫简单许多,只要按照接口规范就很容易获取数据。

豆瓣 API 有比较详细的文档,各位可自行查阅。在文档中,我看到了两个比较合适的接口:

Top250(/v2/movie/top250),获取豆瓣电影排行榜前 250 部电影列表;

电影条目信息(/v2/movie/subject/:id),获取一部电影的详细信息。

所以我打算在抓取信息代码中,首先通过 Top250 接口获取 250 部电影的 id,之后再根据 id 查询每一部的详细信息。

这个代码并不作为网站功能的一部,而是直接通过命令行运行。如果你想在网页上实现此功能,会有一个问题,就是抓取过程是个很耗时的事情,但一个网页请求并不能等待很久,如果一段时间未返回,这个请求就会关闭。暂时我们还不需要去解决这个问题。

首先获取 Top250。使用最基本的 urllib 请求 API:

import urllib

response = urllib.urlopen('#/v2/movie/top250')

data = response.read()

print data

可以看到结果是一长串 json 格式的文本,这就是我们想要的结果。建议在浏览器中打开此 API 地址,并且用 json 插件或工具查看返回信息,这样可以更直观地看到数据的结构。

Python实战【第六节】拿来主义

将 json 格式转换成 dict 对象:

import json

data_json = json.loads(data)

dict 类型的结果中,subjects 对应的是影片 list:

movie250 = data_json['subjects']

for movie in movie250:

print movie['id'], movie['title']

打印出结果,发现只有 20 条。又查了下文档,原来 Top250 接口还有两个可选参数:start 和 count,表示从第几位开始取,取多少条。

那么把代码调整下,外面增加一层循环。为了避免连续请求太快,在每次循环中,通过 time.sleep 方法停顿 3 秒钟。另外,把取到的电影 id 都存入一个变量中:

import urllib

import json

import time

movie_ids = []

for index in range(0, 250 ,50):

print index

response = urllib.urlopen('#/v2/movie/top250?start=%d&count=50' % index)

data = response.read()

# print data

data_json = json.loads(data)

movie250 = data_json['subjects']

for movie in movie250:

movie_ids.append(movie['id'])

print movie['id'], movie['title']

time.sleep(3)

print movie_ids

一切顺利,拿到 250 个 id,接下来就可以进行第二步,获取影片的详细信息了。这里,你可以把打印出的 movie_ids 保存下来,避免后续过程中的重复抓取。

Python实战【第六节】拿来主义

为了能把抓取到的数据保存下来,先对我们之前的数据库做一些改动。结合文档中对条目信息的说明,决定在数据库中记录以下字段:

id - 影片 id

title - 中文名

origin - 原名

url - 影片豆瓣链接

rating - 评分

image - 海报图片地址

directors - 导演

casts - 主演

year - 年代

genres - 类型

countries - 制片国家/地区

summary - 简介

在数据库中执行:

create table movie (id, title, origin, url, rating, image, directors, casts, year, genres, countries, summary);

添加数据的 sql 语句不需要了,我们将通过抓取程序来添加。

直接复用 web.py 里的数据库方法:

import web

db = web.database(dbn='sqlite', db='MovieSite.db')

观察一下条目信息 API 的格式,增加一个将此格式数据存入数据库的方法:

def add_movie(movie):

movie = json.loads(data)

print movie['title']

db.insert('movie',

id=int(movie['id']),

title=movie['title'],

origin=movie['original_title'],

url=movie['alt'],

image=movie['images']['large'],

directors=','.join([d['name'] for d in movie['directors']]),

casts=','.join([c['name'] for c in movie['casts']]),

year=movie['year'],

genres=','.join(movie['genres']),

countries=','.join(movie['countries']),

summary=movie['summary'],

)

之后,就是开始让程序反复地去请求、转换、存储。同样,用 sleep 保持节奏,另外 print 出一些信息,以便于了解抓取的进度。这么做也是为了在程序意外中断后,可以手动从中断处开始继续抓取。

count = 0

for mid in movie_ids:

print count, mid

response = urllib.urlopen('#/v2/movie/subject/%s' % mid)

data = response.read()

add_movie(data)

count += 1

time.sleep(3)

一切就绪,奔跑吧,程序!向着 250 部电影数据。

现在再运行网站,数据已经比较丰富了。不过因为数据库表名的变动,详细数据页会有错误。这个小修改就留给你们自己了。

恭喜您在Python自学的道路上又坚持了一天,我们目前学习的知识比之前的要复杂一些,但是也比之前的有趣多了,所以希望大家跟上我们的步伐,继续加油!

免责声明:内容和图片源自网络,版权归原作者所有,如有侵犯您的原创版权请告知,我们将尽快删除相关内容。

预约申请免费试听课

填写下面表单即可预约申请免费试听! 怕学不会?助教全程陪读,随时解惑!担心就业?一地学习,可全国推荐就业!

上一篇:Python实战【第五节】搜一下
下一篇:Python实战【第七节】放开那只海豹

【Git第八节】移除文件

【Python实战】四行Python代码就能知道你那的天气,你敢信?

Python实战【用Python写游戏第十三节】exe打包

Python实战【用Python写游戏第十二节】屡败屡战

  • 扫码领取资料

    回复关键字:视频资料

    免费领取 达内课程视频学习资料

Copyright © 2023 Tedu.cn All Rights Reserved 京ICP备08000853号-56 京公网安备 11010802029508号 达内时代科技集团有限公司 版权所有

选择城市和中心
黑龙江省

吉林省

河北省

湖南省

贵州省

云南省

广西省

海南省