Crossin的编程教室

标题: Python 实战(7):连连看 [打印本页]

作者: crossin先生    时间: 2015-5-31 23:42
标题: Python 实战(7):连连看
上次课在详细页面上加了海报。除此之外,数据库里还有其他很多信息我们没有用上,比如演员和导演。这些信息还有个重要的作用,就是把不同的影片关联起来。比如你看了一部电影,对其主演感兴趣,自然就想知道他还演过什么影片。现在,我们就来用演员信息把不同的影片连起来。

仔细看过之前抓取豆瓣影片信息的代码就会发现,豆瓣 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)




作者: yinxuexia1204    时间: 2016-8-8 16:53
本帖最后由 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
作者: crossin先生    时间: 2016-8-9 17:02
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
作者: yinxuexia1204    时间: 2016-8-9 17:09
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
作者: crossin先生    时间: 2016-8-9 22:19
yinxuexia1204 发表于 2016-8-9 17:09
是的,我写成小写get了,改后就没问题了,但出现新问题

class cast:

浏览器和代码运行环境的文字编码不一样。
你这里用 cast_name.encode('utf8') 看看。
其实建议不要用中文来作为url参数,会比较麻烦,用id会更好
作者: yinxuexia1204    时间: 2016-8-10 09:06
crossin先生 发表于 2016-8-9 22:19
浏览器和代码运行环境的文字编码不一样。
你这里用 cast_name.encode('utf8') 看看。
其实建议不要用中文 ...

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

python3的str也有encode。也可能要 cast_name.encode('utf8').decode('gbk')
另外你这问题可能只存在于你print的时候。网页显示也许没问题
这个要你自己调试看。不在你的环境,我也没法保证说得对
作者: yinxuexia1204    时间: 2016-8-10 15:17
crossin先生 发表于 2016-8-10 10:30
python3的str也有encode。也可能要 cast_name.encode('utf8').decode('gbk')
另外你这问题可能只存在于你 ...

是的,只是打印的时候会报错,在IDLE打印就没问题,但是无论怎么样,查询的结果是0条,很纳闷,这节课之前的都调试成功,这节课点击演员名后,页面也跳转成功,但是在显示电影名称处显示空白
作者: crossin先生    时间: 2016-8-11 11:09
yinxuexia1204 发表于 2016-8-10 15:17
是的,只是打印的时候会报错,在IDLE打印就没问题,但是无论怎么样,查询的结果是0条,很纳闷,这节课之 ...

牵涉到好几处的编码:浏览器、代码、数据库、控制台,要保证一致才行。尤其windows系统,因为系统默认是gbk,和通常的utf8不符,所以会麻烦。
可以先用全英文数据,把代码运行起来。之后再调试编码的问题

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

我直接给一个变量赋值"张国荣",然后带入sql语句查询,是可以正常显示的,但是通过网页点击张国荣,就查询结果为0;不知道需要将哪里也设置下
作者: crossin先生    时间: 2016-8-15 14:43
yinxuexia1204 发表于 2016-8-15 10:14
我直接给一个变量赋值"张国荣",然后带入sql语句查询,是可以正常显示的,但是通过网页点击张国荣,就查 ...

应该是你代码里的编码和网页获取的编码不一样
你把网页获取的值 print 出来看
作者: yinxuexia1204    时间: 2016-8-15 14:53
yinxuexia1204 发表于 2016-8-15 10:14
我直接给一个变量赋值"张国荣",然后带入sql语句查询,是可以正常显示的,但是通过网页点击张国荣,就查 ...

打印的时候就会提示:'gbk' codec can't encode character '\xe5' in position 0: illegal multibyte sequence
也尝试把浏览器设置为utf-8,不过还是这样
作者: crossin先生    时间: 2016-8-16 14:48
yinxuexia1204 发表于 2016-8-15 14:53
打印的时候就会提示:'gbk' codec can't encode character '\xe5' in position 0: illegal multibyte seq ...

print content.encode('utf8')
系统默认用gbk解码,所以会报错
作者: yinxuexia1204    时间: 2016-8-16 15:49
crossin先生 发表于 2016-8-16 14:48
print content.encode('utf8')
系统默认用gbk解码,所以会报错

转换后,还进行了str(),然后打印出b'\xc3\xa5\xc2\xbc\xc2\xa0\xc3\xa5\xc2\x9b\xc2\xbd\xc3\xa8\xc2\x8d\xc2\xa3'
带入sql中查询是没结果的,实际点击的是张国荣,查询应该有结果
作者: crossin先生    时间: 2016-8-17 11:12
yinxuexia1204 发表于 2016-8-16 15:49
转换后,还进行了str(),然后打印出b'\xc3\xa5\xc2\xbc\xc2\xa0\xc3\xa5\xc2\x9b\xc2\xbd\xc3\xa8\xc2\x8d ...

要转成正确编码的字符才能查到结果,现在这个b'...'肯定是不行的。但我现在不可能模拟你的环境,也不清楚每一步拿到的变量的数据类型,所以你要自己调试。
建议尝试:content.decode('gbk').encode('utf8')
可以去下一个chardet的库帮助确定编码,同时结合 type() 查看数据类型,然后做正确的转换。数据库应该是utf8的,所以应该最后要转成 utf8 的字符
作者: shmxz1989    时间: 2017-2-8 00:07
我也碰到这个问题,点击演员名字的超链接出来的页面没有电影信息,空的。但是点击导演名字的超链接却是正常的。检查了代码,完全一致的,不知问题出在哪里......
作者: crossin先生    时间: 2017-2-8 15:15
shmxz1989 发表于 2017-2-8 00:07
我也碰到这个问题,点击演员名字的超链接出来的页面没有电影信息,空的。但是点击导演名字的超链接却是正常 ...

如果你是python3的话。
通常如我上面所说,是编码不一致导致无法找到匹配的字符。
你可以先试试纯英文的数据是不是正常。

如果确认是中文问题,就要用我上面说的转换编码,保证编码一致再去数据库里查。

不过你现在导演正常,演员不正常,倒是有一点奇怪
作者: shmxz1989    时间: 2017-2-8 21:03
crossin先生 发表于 2017-2-8 15:15
如果你是python3的话。
通常如我上面所说,是编码不一致导致无法找到匹配的字符。
你可以先试试纯英文的 ...

感谢C大,我用的python2.7(目前还在windows下)。
已发现错误所在,不在于编码,是个低级错误(掩面),昨天夜里一定是太困了,郁闷了那么久竟然没发现,哈哈哈~
作者: crossin先生    时间: 2017-2-9 14:18
shmxz1989 发表于 2017-2-8 21:03
感谢C大,我用的python2.7(目前还在windows下)。
已发现错误所在,不在于编码,是个低级错误(掩面), ...

一般很诡异无法理解的错误,最后发现往往都是一些低级原因
作者: wuyuhub46    时间: 2018-3-21 09:29
shmxz1989 发表于 2017-2-8 21:03
感谢C大,我用的python2.7(目前还在windows下)。
已发现错误所在,不在于编码,是个低级错误(掩面), ...

啥错误啊,我也碰到这错误,演员能出来,但导演页面404错误
作者: wuyuhub46    时间: 2018-3-21 09:35
wuyuhub46 发表于 2018-3-21 09:29
啥错误啊,我也碰到这错误,演员能出来,但导演页面404错误

哈哈  找到错误了  也是大晚上  没找到
作者: 2894386560    时间: 2018-5-14 16:23
先生,我碰到个问题,点击演员的链接的时候有的演员链接可以正常跳转到电影,有的跳转不了会出现图3的错误,错误的代码是图1,有点搞不懂。
然后导演的链接都显示404 not found ,这个的错误还没能找到。

3.png (9.84 KB, 下载次数: 339)

图3

图3

1.png (60.27 KB, 下载次数: 335)

图1

图1


作者: 2894386560    时间: 2018-5-14 16:28
2894386560 发表于 2018-5-14 16:23
先生,我碰到个问题,点击演员的链接的时候有的演员链接可以正常跳转到电影,有的跳转不了会出现图3的错误 ...

404 not found  的错误找到了。。。然后改完之后点击导演的链接就会出现和点击演员的链接一样的错误了……
作者: crossin先生    时间: 2018-5-14 22:59
2894386560 发表于 2018-5-14 16:28
404 not found  的错误找到了。。。然后改完之后点击导演的链接就会出现和点击演员的链接一样的错误了… ...

大概是中文编码问题
建议修改下代码,不要通过演员名字,而是通过一个id来对应演员
作者: skybeak    时间: 2018-5-15 11:35
您好:
     我用的是python35,
class director:
    def GET(self, director_name):
        condition = r'directors like "%' + director_name + r'%"'
        movies = db.select('moviee', where=condition)
        return render.index5(movies)
时,无法搜索到相应的内容;
class director:
    def GET(self, director_name):
        director_name = ‘具体的某个名字时’
        condition = r'directors like "%' + director_name + r'%"'
        movies = db.select('moviee', where=condition)
        return render.index5(movies)
时,可以显示相应的内容。
       我感觉是编码方式的问题,错误'gbk' codec can't decode byte 0xa2 in position 268: illegal multibyte sequence,想请教下老师解决方法。
作者: crossin先生    时间: 2018-5-16 09:41
skybeak 发表于 2018-5-15 11:35
您好:
     我用的是python35,
class director:

如果你是用windows,你可能需要全部都指明为 gbk 会好些
这个编码问题可能很多。建议你先用英文把程序调通
作者: skybeak    时间: 2018-5-16 11:15
在这个方法中,def GET(self, director_name):
通过打印  director_name 的值为  å¼—兰克·德拉邦特
转换成utf-8后显示的是:b'\xc3\xa5\xc2\xbc\xc2\x97\xc3\xa5\xc2\x85\xc2\xb0\xc3\xa5\xc2\x85\xc2\x8b\xc3\x82\xc2\xb7\xc3\xa5\xc2\xbe\xc2\xb7\xc3\xa6\xc2\x8b\xc2\x89\xc3\xa9\xc2\x82\xc2\xa6\xc3\xa7\xc2\x89\xc2\xb9'
这个还是转换编码不对么?转换成utf-8后是不是应该是 具体的人名才对?
另外方法中 director_name的值是来自于movie.html中的<a href="/director/$director">$director</a>的$director么?
作者: crossin先生    时间: 2018-5-17 22:41
skybeak 发表于 2018-5-16 11:15
在这个方法中,def GET(self, director_name):
通过打印  director_name 的值为  å¼—兰克·å ...

还是编码的问题,但不通过调试,我也很难看出是哪里的问题。公众号回复 编码 ,有几篇文章

是的
作者: Min1001    时间: 2018-11-15 17:26
请问一下为什么有些人名信息打开正常,有些为什么却是下面这种情况呢

QQ图片20181115092332.png (81.62 KB, 下载次数: 340)

QQ图片20181115092332.png


作者: crossin先生    时间: 2018-11-15 21:27
Min1001 发表于 2018-11-15 17:26
请问一下为什么有些人名信息打开正常,有些为什么却是下面这种情况呢

从这个信息我也看不出来

你最好定位下报错放生在哪段代码,并把报错前的相关变量值print出来看看有没有什么异常




欢迎光临 Crossin的编程教室 (https://bbs.crossincode.com/) Powered by Discuz! X2.5