设为首页收藏本站

Crossin的编程教室

 找回密码
 立即加入
查看: 38106|回复: 29
打印 上一主题 下一主题

Python 实战(7):连连看

[复制链接]

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

跳转到指定楼层
楼主
发表于 2015-5-31 23:42:04 |只看该作者 |倒序浏览
上次课在详细页面上加了海报。除此之外,数据库里还有其他很多信息我们没有用上,比如演员和导演。这些信息还有个重要的作用,就是把不同的影片关联起来。比如你看了一部电影,对其主演感兴趣,自然就想知道他还演过什么影片。现在,我们就来用演员信息把不同的影片连起来。

仔细看过之前抓取豆瓣影片信息的代码就会发现,豆瓣 API 中是以列表形式提供演员和导演信息。而我在抓取时,将其简化,只是选取了其中的姓名,用逗号(,)拼接起来,作为一个字符串存储在数据库中。因此,如果只是想显示出这些信息,可以简单地实现:

<p>主演:$movie.casts</p>

不过现在我们不仅仅要显示主演的名字,还希望能通过主演关联到其他影片。所以这里需要把这些名字分开,并分别加上超链接。

之前课程中说过,web.py 模板可以让你在 HTML 里写 Python。我们现在就需要在模板里对主演名称的字符串做一些处理:

$ casts = movie.casts.split(',')
<p>主演:
$for cast in casts:
    <a href="">$cast</a>
</p>

$ 符号开头的代码将会以 Python 的语法执行。需要特别注意的是,$ casts 之间有一个不可缺少的空格,这个空格说明这里是定义了一个新的变量 casts,而不是获取变量 casts 的值。

通过 split 方法将主演名字拆分成一个字符串列表,再通过 for 循环,将其中每一项拿出,加上 a 标签,做成一个超链接。超链接的地址暂时为空,我们还没有能够处理点击演员名的合适页面。

此时刷新页面,可以看到详细页面上已有了演员信息,并且每个名字下面有一个下划线。只是点击之后并不会有特别的反应。

我们是通过在页面模板中处理演员信息,当然你也可以选择另一种方法,即在后台的响应函数,也就是 class movie 的 GET 方法中,将演员信息处理好,作为额外一项参数传递给模板。

那么接下来的问题,点击了演员名称之后要如何处理。我的想法是进行一次搜索,搜索所有影片演员信息中包含此演员名的电影。因为我们的演员信息是一个字符串存储的,所以可以采用之前搜影片名称类似的方法进行。这样会比较省事,但不足之处是,无法区分名字相同或部分相同的情况。而搜索结果的显示,则可以直接复用 index 模板。

首先在 url 里添加跳转规则:

urls = (
    '/', 'index',
    '/movie/(.*)', 'movie',
    '/cast/(.*)', 'cast',
)

然后是处理的方法:

class cast:
    def GET(self, cast_name):
        condition = r'casts like "%' + cast_name + r'%"'
        movies = db.select('movie', where=condition)
        return render.index(movies)

此处的 GET 方法和 index 里的 POST 方法差不多,唯一不同只是把搜索条件从 title 改为 casts。

最后,再把新增的跳转地址加入到刚刚空着的 a 标签里:

<a href="/cast/$cast">$cast</a>

这里几个名称都用了“cast”,别搞混了。为了区分对于,你也可以分别改为其他名字 cast_name、url_cast、cast_value 等。

这样就已完成演员名的搜索。现在再点击演员名,就可以跳转到搜索结果的页面。

然而,这时候你很可能发现,点击搜索出的结果,并不能再跳转到其他电影的页面(至少我这里是这样)。看了一下,页面被跳转去了

http://127.0.0.1:8080/cast/movie/123456

而不是预想的

http://127.0.0.1:8080/movie/123456

查了代码,原来 问题出在 a 标签的 href 属性上:

"movie/$movie['id']"

前面没有加 /,是表示当前页面下的 movie/xxx 地址,而加了 / 才表示主域名下的 movie/xxx 地址。之前都是从主域名下进行搜索,跳转不会有问题了,而现在一旦使用在 /casts 页面下,跳转就不对了。只要多加上 /,改为

<a href="/movie/$movie['id']">$movie['title']</a>

就没有问题了。

以同样的方式,可以再把导演信息加入搜索功能,这里就不再赘述,各位自行完成。

试着搜了下,发现豆瓣的 top250 里还是比较偏重华语片和老片的。比如张国荣的有 8 部,而克里斯蒂安·贝尔只有 2 部。

code.py (1.16 KB, 下载次数: 297)
movie.html (450 Bytes, 下载次数: 188)



#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

62

积分

注册会员

Rank: 2

沙发
发表于 2016-8-8 16:53:15 |只看该作者
本帖最后由 yinxuexia1204 于 2016-8-9 17:03 编辑

class cast:
    def GET(self, cast_name):
    print(cast_name)

打印的时候会报错:'gbk' codec can't encode character '\xe5' in position 0: illegal multibyte sequence
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

板凳
发表于 2016-8-9 17:02:33 |只看该作者
yinxuexia1204 发表于 2016-8-8 16:53
点击主演名称,跳转到http://127.0.0.1:8080/cast/%E8%AE%A9%C2%B7%E9%9B%B7%E8%AF%BA,其实看的是http://1 ...

地址那个应该没问题,只是正常的url文字转码。
405应该是GET和POST设置错了。你是不是设成了POST
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

62

积分

注册会员

Rank: 2

地板
发表于 2016-8-9 17:09:36 |只看该作者
crossin先生 发表于 2016-8-9 17:02
地址那个应该没问题,只是正常的url文字转码。
405应该是GET和POST设置错了。你是不是设成了POST ...

是的,我写成小写get了,改后就没问题了,但出现新问题

class cast:
    def GET(self, cast_name):
    print(cast_name)

打印的时候会报错:'gbk' codec can't encode character '\xe5' in position 0: illegal multibyte sequence
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

5#
发表于 2016-8-9 22:19:59 |只看该作者
yinxuexia1204 发表于 2016-8-9 17:09
是的,我写成小写get了,改后就没问题了,但出现新问题

class cast:

浏览器和代码运行环境的文字编码不一样。
你这里用 cast_name.encode('utf8') 看看。
其实建议不要用中文来作为url参数,会比较麻烦,用id会更好
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

62

积分

注册会员

Rank: 2

6#
发表于 2016-8-10 09:06:48 |只看该作者
crossin先生 发表于 2016-8-9 22:19
浏览器和代码运行环境的文字编码不一样。
你这里用 cast_name.encode('utf8') 看看。
其实建议不要用中文 ...

python3没有encode这个,老师你不就是用的中文嘛,也不是Id呀,根据演员名来看其还演过哪些电影,貌似Id没法用吧
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

7#
发表于 2016-8-10 10:30:16 |只看该作者
yinxuexia1204 发表于 2016-8-10 09:06
python3没有encode这个,老师你不就是用的中文嘛,也不是Id呀,根据演员名来看其还演过哪些电影,貌似Id ...

python3的str也有encode。也可能要 cast_name.encode('utf8').decode('gbk')
另外你这问题可能只存在于你print的时候。网页显示也许没问题
这个要你自己调试看。不在你的环境,我也没法保证说得对
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

62

积分

注册会员

Rank: 2

8#
发表于 2016-8-10 15:17:06 |只看该作者
crossin先生 发表于 2016-8-10 10:30
python3的str也有encode。也可能要 cast_name.encode('utf8').decode('gbk')
另外你这问题可能只存在于你 ...

是的,只是打印的时候会报错,在IDLE打印就没问题,但是无论怎么样,查询的结果是0条,很纳闷,这节课之前的都调试成功,这节课点击演员名后,页面也跳转成功,但是在显示电影名称处显示空白
回复

使用道具 举报

174

主题

45

好友

11万

积分

管理员

Rank: 9Rank: 9Rank: 9

9#
发表于 2016-8-11 11:09:00 |只看该作者
yinxuexia1204 发表于 2016-8-10 15:17
是的,只是打印的时候会报错,在IDLE打印就没问题,但是无论怎么样,查询的结果是0条,很纳闷,这节课之 ...

牵涉到好几处的编码:浏览器、代码、数据库、控制台,要保证一致才行。尤其windows系统,因为系统默认是gbk,和通常的utf8不符,所以会麻烦。
可以先用全英文数据,把代码运行起来。之后再调试编码的问题
#==== Crossin的编程教室 ====#
微信ID:crossincode
网站:http://crossincode.com
回复

使用道具 举报

0

主题

0

好友

62

积分

注册会员

Rank: 2

10#
发表于 2016-8-15 10:14:05 |只看该作者
crossin先生 发表于 2016-8-11 11:09
牵涉到好几处的编码:浏览器、代码、数据库、控制台,要保证一致才行。尤其windows系统,因为系统默认是gb ...

我直接给一个变量赋值"张国荣",然后带入sql语句查询,是可以正常显示的,但是通过网页点击张国荣,就查询结果为0;不知道需要将哪里也设置下
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即加入

QQ|手机版|Archiver|Crossin的编程教室 ( 苏ICP备15063769号  

GMT+8, 2024-11-23 17:53 , Processed in 0.018600 second(s), 27 queries .

Powered by Discuz! X2.5

© 2001-2012 Comsenz Inc.

回顶部