Crossin的编程教室

标题: Python 实战(6):放开那只海豹 [打印本页]

作者: crossin先生    时间: 2015-5-24 23:40
标题: Python 实战(6):放开那只海豹
有了一堆数据后,现在可以把影片详细页面做得更详细一点了。

首先能想到的,就是加上影片的海报。在从豆瓣获取的数据里,有一项 image,就是影片海报图片的地址。如:

http://img4.douban.com/view/movie_poster_cover/lpst/public/p1910830216.jpg

把地址贴在浏览器中,就可以看到海报图片。

HTML 里显示图片的语法是:

<img src="图片地址">

于是,在模板 movie.html 里增加:

<img src="$movie.image">

保存后刷新页面。结果,并没有如我们所愿看到影片的海报图片。把 src 换成其他一些网络图片的地址,是可以正常显示的。这里代码并没有错,问题的原因在于豆瓣的图片限制了从外部网站直接访问,也就是通常说的“防盗链”。

既然如此,那我只好选择另一种方法:把电影海报图片抓到本地,之后页面上直接显示自身服务器上的图片。

基本思路就是,从已经拿到的数据库信息中,依次取出海报地址,访问后将其保存为本地文件,以影片 id 命名。页面上,通过 id 拼出图片的文件名,将其显示。(这里,因为我已经检验过所有图片格式均为 jpg,所以可以直接这么做,如果海报有多种图片格式,那么仅通过 id 来拼文件名是不够的。)

下载图片的方法:

def get_poster(id, url):
    pic = urllib.urlopen(url).read()
    file_name = 'poster/%d.jpg' % id
    f = file(file_name, "wb")
    f.write(pic)
    f.close()

file 里的 wb 参数表示以二进制的方式写入文件。在调用此方法时,需确保当前目录下有一个叫做 poster 的目录,不然程序是没有办法访问到文件的。

db = web.database(dbn='sqlite', db='MovieSite.db')
movies = db.select('movie')
count = 0
for movie in movies:
    get_poster(movie.id, movie.image)
    count += 1
    print count, movie.title
    time.sleep(2)

从数据库里取出 id 和海报图片地址,循环抓取,每次输出进度和标题,并休息 2 秒钟。

运行抓取程序,下载完所有图片之后,修改一下 movie.html,加入一行:

<img src="/static/poster/$(movie.id).jpg">

这里有两件事需要注意:

首先是图片的路径。这里要在页面上直接使用文件而不是代码,这被称作静态文件访问。在 web.py 里,默认是以 static 作为静态文件目录。因此,必须把存放图片的 poster 文件夹扔到 static 目录下面。static 目录本身是在服务器根目录,也就是和 code.py 在一个目录下。

其次是 $(movie.id).jpg。这里如果不加括号,代码则会将 .jpg 理解为取参数 movie.id.jpg 的值。所以要用括号来区分。

好了,我们的网站终于不再是一个纯文字网站了。

someweb-6-movie.html (208 Bytes, 下载次数: 138)
get_poster.py (409 Bytes, 下载次数: 146)



作者: 喵小白    时间: 2015-5-25 20:58
如何提高插入大量数据的效率呢?
作者: crossin先生    时间: 2015-5-26 20:14
喵小白 发表于 2015-5-25 20:58
如何提高插入大量数据的效率呢?

sql有批量插入方法
作者: 喵小白    时间: 2015-5-27 09:21
crossin先生 发表于 2015-5-26 20:14
sql有批量插入方法

是不是先把数据保存到文件里,然后从文件导入数据?
作者: crossin先生    时间: 2015-5-27 20:16
喵小白 发表于 2015-5-27 09:21
是不是先把数据保存到文件里,然后从文件导入数据?

不用啊,直接存在内存里,先用变量保存着,按格式整理好,然后用批量插入命令一次插入就可以
作者: 喵小白    时间: 2015-5-28 15:19
crossin先生 发表于 2015-5-27 20:16
不用啊,直接存在内存里,先用变量保存着,按格式整理好,然后用批量插入命令一次插入就可以 ...

哦~~~酱紫
作者: lovepythoner    时间: 2015-7-7 01:34
请问老师,为什么仅仅是一个urllib.urlopen加载一张图片就要1分多钟?
import urllib
f=urllib.urlopen("http://img6.douban.com/img/celebrity/large/17525.jpg").read()
fi=file("17525.jpg","wb")
fi.write(f)
fi.close()
以上代码执行完要1~2分钟
而用浏览器打开该网址则是瞬间打开?
试过urllib2.urlopen也几乎是瞬间打开

import urllib2

f=urllib2.urlopen("http://img6.douban.com/img/celebrity/large/17525.jpg").read()
fi=file("17525.jpg","wb")
fi.write(f)
fi.close()
以上代码几乎瞬间执行完毕

是不是urllib2更高效?
谢谢老师
作者: crossin先生    时间: 2015-7-7 13:28
lovepythoner 发表于 2015-7-7 01:34
请问老师,为什么仅仅是一个urllib.urlopen加载一张图片就要1分多钟?
import urllib
f=urllib.urlopen("htt ...

没专门研究过,每次都是这么久的话,那应该是实现上的差别
作者: lincoln    时间: 2015-7-17 23:02
请问老师,top250都列出来以后,搜索功能不能搜索中文了

<type 'exceptions.UnicodeDecodeError'> at /
'ascii' codec can't decode byte 0xe7 in position 48: ordinal not in range(128)

好像是编码问题,请问怎么解决?谢谢!
作者: crossin先生    时间: 2015-7-18 15:57
lincoln 发表于 2015-7-17 23:02
请问老师,top250都列出来以后,搜索功能不能搜索中文了

at /

要看是哪里报的错,用encode('utf8')
作者: crossin先生    时间: 2015-7-18 15:57
lincoln 发表于 2015-7-17 23:02
请问老师,top250都列出来以后,搜索功能不能搜索中文了

at /

要看是哪里报的错,用encode('utf8')
作者: lincoln    时间: 2015-7-26 10:19
crossin先生 发表于 2015-7-18 15:57
要看是哪里报的错,用encode('utf8')

老师您好,我搜了一下,在前面加上这些就可以了

import sys
#print sys.getdefaultencoding()
reload(sys)
sys.setdefaultencoding('UTF-8')
#print sys.getdefaultencoding()

这样改默认编码方式会有问题吗?
作者: crossin先生    时间: 2015-7-26 15:10
lincoln 发表于 2015-7-26 10:19
老师您好,我搜了一下,在前面加上这些就可以了

import sys

这个不清楚,有时候控制台的编码不是utf8,输出会有问题。不过先解决这,有问题了再想办法吧
作者: 阳阳学通信    时间: 2016-7-25 14:20
本帖最后由 阳阳学通信 于 2016-7-25 14:23 编辑

老师,我直接在movie.html中加入<img src="$movie.image">是可以显示图片的,但是抓取图片到本地以后,放在poster目录下,图片显示不出来,请教一下?

疑惑.png (19.89 KB, 下载次数: 227)

疑惑.png

目录.png (28.08 KB, 下载次数: 217)

目录.png


作者: crossin先生    时间: 2016-7-26 14:51
阳阳学通信 发表于 2016-7-25 14:20
老师,我直接在movie.html中加入是可以显示图片的,但是抓取图片到本地以后,放在poster目录下,图片显示不 ...

没定义static目录,或static配置不正确
作者: 阳阳学通信    时间: 2016-7-27 16:55
crossin先生 发表于 2016-7-26 14:51
没定义static目录,或static配置不正确

谢谢老师,QQ群已经为我解答过了~~
作者: nekonekobox    时间: 2017-3-16 00:13
crossin老师,我也图片显示不出来
QQ截图20170316001233.png
作者: crossin先生    时间: 2017-3-16 17:56
nekonekobox 发表于 2017-3-16 00:13
crossin老师,我也图片显示不出来

具体看页面上的显示路径是怎样?往往是多个斜杠少个斜杠之类
作者: nekonekobox    时间: 2017-3-18 00:37
crossin先生 发表于 2017-3-16 17:56
具体看页面上的显示路径是怎样?往往是多个斜杠少个斜杠之类

果然是少了个/,就在<img src="/static/poster/$(movie.id).jpg"/>这个地方
python的写文件的时候前面是不带的,file_name='static/poster/%d.jpg'%id
但是html的图片链接这里还是得带上
作者: 不会飞的hjh    时间: 2017-9-10 13:52
请问一下先生,搜索的时候提示错误为 "HTTP/1.1 POST /" - 405 Method Not Allowed  不是很清楚问题所在,在网上查询到的说是不允许静态文件响应post请求,要求把method=post改为=get,这样的方法也是无果,应该怎么解决呢?
作者: crossin先生    时间: 2017-9-10 15:12
不会飞的hjh 发表于 2017-9-10 13:52
请问一下先生,搜索的时候提示错误为 "HTTP/1.1 POST /" - 405 Method Not Allowed  不是很清楚问题所在, ...

你发出来的还是 POST 请求,你要改成 get
或者把代码里的 GET 改成 POST,总归要一致
作者: 不会飞的hjh    时间: 2017-9-12 11:37
crossin先生 发表于 2017-9-10 15:12
你发出来的还是 POST 请求,你要改成 get
或者把代码里的 GET 改成 POST,总归要一致 ...

被自己蠢哭,原来是自己代码里里的POST方法写成POSE了,现在改回,可以搜索,谢谢先生的耐心回复!
作者: 13253620252    时间: 2017-12-4 22:34
先生,按照您给的代码,为什么会提示如下错误?在上一课中,是能获取到1292052这个电影网址的。

捕获.PNG (6.25 KB, 下载次数: 226)

捕获.PNG


作者: crossin先生    时间: 2017-12-5 00:17
13253620252 发表于 2017-12-4 22:34
先生,按照您给的代码,为什么会提示如下错误?在上一课中,是能获取到1292052这个电影网址的。
...

你没有poster这个目录吧,先创建好
作者: 13253620252    时间: 2017-12-5 21:24
crossin先生 发表于 2017-12-5 00:17
你没有poster这个目录吧,先创建好

先生,上面的问题已经解决。但是在运行代码抓取图片时,只能抓取到16张海报,还会出现重复抓取的情况,这是怎么回事呢?

捕获.PNG (8.78 KB, 下载次数: 213)

捕获.PNG


作者: crossin先生    时间: 2017-12-6 14:49
13253620252 发表于 2017-12-5 21:24
先生,上面的问题已经解决。但是在运行代码抓取图片时,只能抓取到16张海报,还会出现重复抓取的情况,这 ...

先确认数据库里的数据
作者: zhaolehua    时间: 2017-12-14 11:36
先生,我想直接在影片id上加个超级链接,是不是像前面在文字上加超级链接一样?
作者: crossin先生    时间: 2017-12-14 14:17
zhaolehua 发表于 2017-12-14 11:36
先生,我想直接在影片id上加个超级链接,是不是像前面在文字上加超级链接一样? ...


作者: zhaolehua    时间: 2017-12-14 15:18
crossin先生 发表于 2017-12-14 14:17

<type 'exceptions.NameError'> at /movie/1292052
global name 'director' is not defined

我想加个导演的超链接,结果出错了,我数据库,.html文件,.py文件里面都定义了,但是还报错。
我如法炮制的演员超链接,现在没有头绪,先生可以指点一下吗?
作者: zhaolehua    时间: 2017-12-14 15:22
zhaolehua 发表于 2017-12-14 15:18
at /movie/1292052
global name 'director' is not defined

<a href="/directors/$directors">$directors</a>
这是我给导演加的超链接
作者: zhaolehua    时间: 2017-12-14 15:33
zhaolehua 发表于 2017-12-14 15:22
$directors
这是我给导演加的超链接

我知道了 我前面没有定义$ directors = movie.directors
作者: crossin先生    时间: 2017-12-15 20:28
到底 director 还是 directors,你先确认没拼错
作者: skybeak    时间: 2018-5-14 09:42
老师,你好:
     我看老师在文章里有这个提示  (首先是图片的路径。这里要在页面上直接使用文件而不是代码,这被称作静态文件访问。在 web.py 里,默认是以 static 作为静态文件目录。因此,必须把存放图片的 poster 文件夹扔到 static 目录下面。static 目录本身是在服务器根目录,也就是和 code.py 在一个目录下。)
     是不是想载入图片只能通过static目录?  我在这个地方没用static,写的是绝对路径<img src="绝对路径">,没有办法显示图片。(绝对路径:<img src="D:/pycharm/WZ/untitled/poster/$(moviee.id).webp">)。
     
作者: crossin先生    时间: 2018-5-14 22:58
skybeak 发表于 2018-5-14 09:42
老师,你好:
     我看老师在文章里有这个提示  (首先是图片的路径。这里要在页面上直接使用文件而不是代 ...

不行
不然通过这个方式不是可以直接从浏览器获取服务器上的任意文件了
作者: boat    时间: 2019-8-19 09:09
本帖最后由 boat 于 2019-8-19 09:19 编辑

图片都下载到poster文件夹下了,但是显示静态文件目录有问题,图片一直出不来,运行程序报错:'StaticApp Object has no attribute 'directory'
在网页中检查,显示error500。
最后查到是python3.7版本的问题,需要修复。
参考文章https://github.com/webpy/webpy/issues/472的最后一个回答找到了解决方案https://github.com/webpy/webpy/pull/468/files
要在报错的web/httpserver.py里的def __init__(self,environ,start_response):
下面加一句self.directory=os.getcwd()
或者可重新安装新的版本
作者: crossin先生    时间: 2019-8-20 22:24
boat 发表于 2019-8-19 09:09
图片都下载到poster文件夹下了,但是显示静态文件目录有问题,图片一直出不来,运行程序报错:'StaticApp O ...

非常感谢你的勘误




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