狠狠撸

狠狠撸Share a Scribd company logo
《浮云脱水小说站》的搭建http://www.zhikanlz.comPython、BeautifulSoup、web.py、 twisted、nginxAuthor: piglei2007@gmail.com
起因 一个寂寞的周末,作者手贱点开了这个“直播贴”翻了十页以后发现贴吧直播贴完全是个 坑爹 的存在…偷懒的程序员,做点什么吧!
想要的结果最初的想法:我需要一个脚本来替我完成抓取帖子中所有楼主的发言,并把它们存成一个静态页面来供阅读我需要:一个解析页面的工具(BeautifulSoup )http://www.crummy.com/software/BeautifulSoup/
Codeimport urllibimport urlparsefrom BeautifulSoup import BeautifulSoupclass BaiduZhibo(object):    """可迭代的对象,不停返回下一页含有给定username的内容(默认为楼主)    返回格式:字典:{            "url": "..."        #当前链接地址"page": 5           #当前页数"content": [...]    #列表,里面有当前页每一个指定username的发言内容}参数:url:    帖子地址
Codeobj_name:   需要抓取的用户昵称,默认为楼主limit:  限定抓取页面的数量,默认无限制html:   设定输出格式,True不做处理,False替换换行符、空格"""    def __init__(self, url, obj_name=None, limit=0, html=False):        … …    def next(self):        if (self.limit and self.counter == self.limit) or (self.nowurl is None):            print "finished."            raise StopIteration        … …    def __iter__(self):        return self    … …if __name__ == ‘__main__’:    # 初始化一个BaiduZhibo对象,然后拼装html页面
Thinking	效果页面虽然已经初步达到了效果,能不能把这个东西升级成一个站点呢。初步想法:管理员(我)可以通过后台来添加帖子的原始url、分类、作者等信息。另外用一个cron来负责根据后台添加的信息抓取生成html页面项目到此分为两个:nowater:负责被cron调用,从数据库查询出小说资源进行抓取工作nowater_web:负责前端web的展示,提供添加小说资源的后台
准备工作Web框架的选择:特点:数据库结构简单(最初设计只有寥寥几张表)业务逻辑简单(展示)web.py (http://webpy.org/)足够简洁换个新鲜的模板引擎(mako)数据库(postgresql)
表结构设计CREATE TABLE "nowater_novel" (    "id" serial NOT NULL PRIMARY KEY,    "title" varchar(100) NOT NULL,    "author" varchar(20) NOT NULL,    "content_type" integer NULL,    --小说类型    "type" varchar(10) NOT NULL default 'baidu',    --来源类型    “url” varchar(200) NOT NULL unique,	--来源url    “update_interval” integer default 10,	--更新间隔    "email" varchar(40) NULL,   --推荐人email,如果有的话    “last_update_floor” integer NOT NULL default 0,	--最后更新的楼层    “last_update_url” varchar(500) NOT NULL,	--最后更新的url    “last_update_time” timestamp with time zone,	--最后更新时间    "ip" varchar(20) NOT NULL default '',    "status" integer NOT NULL default 0,    "jointime" timestamp with time zone NOT NULL DEFAULT CURRENT_TIMESTAMP);NOVEL_STATUS = {     0: u"未初始化",    1: u"更新中...",    2: u"等待更新",    3: u"已完结",    4: u"更新异常",    100: u"已删除"}
项目结构[database]novelsview_countpage_info… …获得小说url等信息添加novel小说源信息#hashff/   #novel id   373/       1.html       2.html       … …[nowater]main.pybasedb.pybaidu_crawler.pywriter.pynovels/… …[nowater_web]web.py包含两个appNovel:浏览脱水小说的前台Admin:一个添加修改小说源的管理后台封装一些简单的对数据库的操作处理对baidu贴吧帖子的抓取逻辑接收格式通用的数据,写入html文件,需要处理分页提供抓取完成的html静态文件5min – main.pyCrontab
问题和解决多线程抓取Threading模块Queue模块抓取内容的分页建立page_info表(字段:page、word_count)在writer.py中集中处理写入逻辑(是否应该分页,分页参数的设置)支持其他社区baidu_crawler.py,封装页面处理逻辑,格式化内容输出由于对输出格式的统一,后期可方便添加tianya_crawler.py … …图片反盗链的处理在**_crawler.py里面对盗链图片url进行预处理使用nginx的反向代理CREATE TABLE "page_info" (    "id" integer NOT NULL PRIMARY KEY,    "page" integer NOT NULL default 1,    "word_count" integer NOT NULL default 0)http://hiphotos./%C2%B9%CD%E8%C3%A8/pic/item/e575bcf5acb72b73730eecf4.jpg-------------------------转换为-------------------------http://www.zhikanlz.com/get_outside_image/hiphotos./%C2%B9%CD%E8%C3%A8/pic/item/e575bcf5acb72b73730eecf4.jpg location ~* ^/get_outside_image/(.*?)/(.*) {                expires 30d;               set $obj_referrer http://$1/;                resolver 8.8.8.8;proxy_pass http://$1/$2;proxy_set_headerreferer $obj_referrer;proxy_set_header host $1;        }
后续问题&补尘辫;改进途径小说源由管理员(我)手动添加效率太低提供迟虫迟下载对天涯社区的支持改进途径:允许用户直接添加原帖地址,并实时的展现抓取的过程从抓取的丑迟尘濒文件生成迟虫迟。新建迟颈补苍测补冲肠谤补飞濒别谤.辫测
准备工作颁辞尘别迟濒辞苍驳-辫辞濒濒颈苍驳基于补箩补虫的长轮询框架选择(罢飞颈蝉迟别诲)
项目结构[nowater_web]web.py包含两个appNovel:  …Admin:  …添加novel小说源信息[database]… …Nginx使用twisted.web维持一个长连接该长连接起到实时返回抓取进度的作用,同时writer.py也通过这个文件提供的http接口与之交互[nowater]main.pybasedb.pybaidu_crawler.pywriter.pylong_looping.pytianya_crawler.py… …提供抓取完成的html静态文件调用http接口驱动爬虫对于抓取进度方面的长连接请求反向代理到这里来
Comet实时显示抓取进度class Progress(resource.Resource):    def render_GET(self, request):        id = request.args.get("id", [""])[0]client_id = request.args.get("client_id", [""])[0]        client = mb.connection_made(id, client_id, request)        if isinstance(client, str):            return client        else:request.notifyFinish().addErrback(self.disconnect, client)            return server.NOT_DONE_YET    def disconnect(self, ret, client):client.request = Noneclient.status = False
Comet实时显示抓取进度 def render_POST(self, request):        """通知某小说更新到了某一页page:            start 开始r_12 表示初始页面的12页o_12 表示小说页面的12页end 结束"""        id = request.args.get("id", [""])[0]        page = request.args.get("page", [""])[0]mb.new_msg(id, page)        return "ok"
问题和解决下载txt文件的实现Nginxsendfilelocation /download_txt/ {            internal;            alias /;}PY:file = get_txt_file(str(id), web.utf8(novel.title))        if file:web.replace_header("Content-Type", "text/plaintext")web.replace_header("Content-Disposition", "attachment; filename=%s.txt" % id)web.header("X-Accel-Redirect", "/download_txt/%s" % file)            return "ok"
生态链baidu_crawler.py… …twistedmain.pywriter.py新帖,先插入帖子的相关信息,调用twisted的接口,开始抓取旧帖,一定更新间隔CometClientweb.py提交帖子地址给web.py如果是已经存在的帖子,直接返回供阅读
Thanks希望Python在中国的应用越来越多Enjoy coding!Author: piglei2007@gmail.com

More Related Content

浮云脱水小说站的搭建