More Related Content
Similar to 浮云脱水小说站的搭建 (20)
浮云脱水小说站的搭建
- 4. Code import urllib import urlparse from BeautifulSoup import BeautifulSoup class BaiduZhibo(object): """ 可迭代的对象,不停返回下一页含有给定username的内容(默认为楼主) 返回格式: 字典:{ "url": "..." #当前链接地址 "page": 5 #当前页数 "content": [...] #列表,里面有当前页每一个指定username的发言内容 } 参数: url: 帖子地址
- 5. Code obj_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页面
- 7. 准备工作 Web框架的选择: 特点: 数据库结构简单(最初设计只有寥寥几张表) 业务逻辑简单(展示) web.py (http://webpy.org/) 足够简洁 换个新鲜的 模板引擎(mako) 数据库(postgresql)
- 8. 表结构设计 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"已删除" }
- 9. 项目结构 [database] novels view_count page_info … … 获得小说url等信息 添加novel小说源信息 #hash ff/ #novel id 373/ 1.html 2.html … … [nowater] main.py basedb.py baidu_crawler.py writer.py novels/ … … [nowater_web] web.py 包含两个app Novel:浏览脱水小说的前台 Admin:一个添加修改小说源的管理后台 封装一些简单的对数据库的操作 处理对baidu贴吧帖子的抓取逻辑 接收格式通用的数据,写入html文件,需要处理分页 提供抓取完成的html静态文件 5min – main.py Crontab
- 10. 问题和解决 多线程抓取 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.baidu.com/%C2%B9%CD%E8%C3%A8/pic/item/e575bcf5acb72b73730eecf4.jpg -------------------------转换为------------------------- http://www.zhikanlz.com/get_outside_image/hiphotos.baidu.com/%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; }
- 13. 项目结构 [nowater_web] web.py 包含两个app Novel: … Admin: … 添加novel小说源信息 [database] … … Nginx 使用twisted.web维持一个长连接 该长连接起到实时返回抓取进度的作用,同时writer.py也通过这个文件提供的http接口与之交互 [nowater] main.py basedb.py baidu_crawler.py writer.py long_looping.py tianya_crawler.py … … 提供抓取完成的html静态文件 调用http接口驱动爬虫 对于抓取进度方面的长连接请求反向代理到这里来
- 14. 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 = None client.status = False
- 15. 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"
- 16. 问题和解决 下载txt文件的实现 Nginxsendfile location /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"
- 17. 生态链 baidu_crawler.py … … twisted main.py writer.py 新帖,先插入帖子的相关信息,调用twisted的接口,开始抓取 旧帖,一定更新间隔 Comet Client web.py 提交帖子地址给web.py 如果是已经存在的帖子,直接返回供阅读