SlideShare uma empresa Scribd logo
1 de 18
《浮云脱水小说站》的搭建 http://www.zhikanlz.com Python、BeautifulSoup、web.py、 twisted、nginx Author: piglei2007@gmail.com
起因  一个寂寞的周末,作者手贱点开了这个“直播贴” 翻了十页以后发现贴吧直播贴完全是个 坑爹 的存在… 偷懒的程序员,做点什么吧!
想要的结果 最初的想法: 我需要一个脚本来替我完成抓取帖子中所有楼主的发言,并把它们存成一个静态页面来供阅读 我需要: 一个解析页面的工具(BeautifulSoup ) http://www.crummy.com/software/BeautifulSoup/
Code import urllib import urlparse from BeautifulSoup import BeautifulSoup class BaiduZhibo(object):     """ 可迭代的对象,不停返回下一页含有给定username的内容(默认为楼主)     返回格式: 字典:{             "url": "..."        #当前链接地址 "page": 5           #当前页数 "content": [...]    #列表,里面有当前页每一个指定username的发言内容 } 参数: url:    帖子地址
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页面
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] 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
问题和解决 多线程抓取 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;         }
后续问题&改进途径 小说源由管理员(我)手动添加效率太低 提供txt下载 对天涯社区的支持 改进途径: 允许用户直接添加原帖地址,并实时的展现抓取的过程 从抓取的html文件生成txt。 新建tianya_crawler.py
准备工作 Comet long-polling 基于ajax的长轮询 框架选择(Twisted)
项目结构 [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接口驱动爬虫 对于抓取进度方面的长连接请求反向代理到这里来
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
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文件的实现 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"
生态链 baidu_crawler.py … … twisted main.py writer.py 新帖,先插入帖子的相关信息,调用twisted的接口,开始抓取 旧帖,一定更新间隔 Comet Client web.py 提交帖子地址给web.py 如果是已经存在的帖子,直接返回供阅读
Thanks 希望Python在中国的应用越来越多 Enjoy coding! Author: piglei2007@gmail.com

Mais conteúdo relacionado

Mais procurados

Http cache 的優化
Http cache 的優化Http cache 的優化
Http cache 的優化振揚 陳
 
Node Web开发实战
Node Web开发实战Node Web开发实战
Node Web开发实战fengmk2
 
部署並執行以太坊智能合約
部署並執行以太坊智能合約部署並執行以太坊智能合約
部署並執行以太坊智能合約Nicholas Lin
 
Node Web开发实战
Node Web开发实战Node Web开发实战
Node Web开发实战fengmk2
 
lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用hugo
 
twMVC#36C#的美麗與哀愁
twMVC#36C#的美麗與哀愁twMVC#36C#的美麗與哀愁
twMVC#36C#的美麗與哀愁twMVC
 
DevOpsDays Taipei 2018 - Puppet 古早味、新感受:改造老牌企業進入自動化時代
DevOpsDays Taipei 2018 - Puppet 古早味、新感受:改造老牌企業進入自動化時代DevOpsDays Taipei 2018 - Puppet 古早味、新感受:改造老牌企業進入自動化時代
DevOpsDays Taipei 2018 - Puppet 古早味、新感受:改造老牌企業進入自動化時代scott liao
 
Monitor is all for ops
Monitor is all for opsMonitor is all for ops
Monitor is all for ops琛琳 饶
 
JCConf2015: groovy to gradle
 JCConf2015: groovy to gradle JCConf2015: groovy to gradle
JCConf2015: groovy to gradleChing Yi Chan
 
twMVC#43 C#10 新功能介紹
twMVC#43 C#10 新功能介紹twMVC#43 C#10 新功能介紹
twMVC#43 C#10 新功能介紹twMVC
 
CP 值很高的 Gulp
CP 值很高的 GulpCP 值很高的 Gulp
CP 值很高的 GulpYvonne Yu
 
RxJS 6 新手入門
RxJS 6 新手入門RxJS 6 新手入門
RxJS 6 新手入門Will Huang
 
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用Shengyou Fan
 
合久必分,分久必合
合久必分,分久必合合久必分,分久必合
合久必分,分久必合Qiangning Hong
 
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩Wen-Tien Chang
 
使用 C#/Razor 開發互動式 WebAssembly 網站 (Modern Web 2018)
使用 C#/Razor 開發互動式 WebAssembly 網站 (Modern Web 2018)使用 C#/Razor 開發互動式 WebAssembly 網站 (Modern Web 2018)
使用 C#/Razor 開發互動式 WebAssembly 網站 (Modern Web 2018)Will Huang
 
Web crawler - Scrapy
Web crawler - Scrapy Web crawler - Scrapy
Web crawler - Scrapy yafish
 
构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 Renaun Erickson
 
NodeJS快速服务端开发 朝沐金风 Shanghai
NodeJS快速服务端开发 朝沐金风 ShanghaiNodeJS快速服务端开发 朝沐金风 Shanghai
NodeJS快速服务端开发 朝沐金风 ShanghaiJackson Tian
 

Mais procurados (20)

Http cache 的優化
Http cache 的優化Http cache 的優化
Http cache 的優化
 
Node Web开发实战
Node Web开发实战Node Web开发实战
Node Web开发实战
 
部署並執行以太坊智能合約
部署並執行以太坊智能合約部署並執行以太坊智能合約
部署並執行以太坊智能合約
 
Node Web开发实战
Node Web开发实战Node Web开发实战
Node Web开发实战
 
lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用lua & ngx_lua 的介绍与应用
lua & ngx_lua 的介绍与应用
 
twMVC#36C#的美麗與哀愁
twMVC#36C#的美麗與哀愁twMVC#36C#的美麗與哀愁
twMVC#36C#的美麗與哀愁
 
DevOpsDays Taipei 2018 - Puppet 古早味、新感受:改造老牌企業進入自動化時代
DevOpsDays Taipei 2018 - Puppet 古早味、新感受:改造老牌企業進入自動化時代DevOpsDays Taipei 2018 - Puppet 古早味、新感受:改造老牌企業進入自動化時代
DevOpsDays Taipei 2018 - Puppet 古早味、新感受:改造老牌企業進入自動化時代
 
Monitor is all for ops
Monitor is all for opsMonitor is all for ops
Monitor is all for ops
 
Java soap
Java soapJava soap
Java soap
 
JCConf2015: groovy to gradle
 JCConf2015: groovy to gradle JCConf2015: groovy to gradle
JCConf2015: groovy to gradle
 
twMVC#43 C#10 新功能介紹
twMVC#43 C#10 新功能介紹twMVC#43 C#10 新功能介紹
twMVC#43 C#10 新功能介紹
 
CP 值很高的 Gulp
CP 值很高的 GulpCP 值很高的 Gulp
CP 值很高的 Gulp
 
RxJS 6 新手入門
RxJS 6 新手入門RxJS 6 新手入門
RxJS 6 新手入門
 
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
以 Kotlin Multiplatform Mobile (KMM) 開發跨平台行動應用
 
合久必分,分久必合
合久必分,分久必合合久必分,分久必合
合久必分,分久必合
 
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
A brief introduction to Vagrant – 原來 VirtualBox 可以這樣玩
 
使用 C#/Razor 開發互動式 WebAssembly 網站 (Modern Web 2018)
使用 C#/Razor 開發互動式 WebAssembly 網站 (Modern Web 2018)使用 C#/Razor 開發互動式 WebAssembly 網站 (Modern Web 2018)
使用 C#/Razor 開發互動式 WebAssembly 網站 (Modern Web 2018)
 
Web crawler - Scrapy
Web crawler - Scrapy Web crawler - Scrapy
Web crawler - Scrapy
 
构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接 构建ActionScript游戏服务器,支持超过15000并发连接
构建ActionScript游戏服务器,支持超过15000并发连接
 
NodeJS快速服务端开发 朝沐金风 Shanghai
NodeJS快速服务端开发 朝沐金风 ShanghaiNodeJS快速服务端开发 朝沐金风 Shanghai
NodeJS快速服务端开发 朝沐金风 Shanghai
 

Destaque

Python在生物研究中的应用浅谈
Python在生物研究中的应用浅谈 Python在生物研究中的应用浅谈
Python在生物研究中的应用浅谈 jondynet
 
Visita a "Los Gabrieles"
Visita a "Los Gabrieles"Visita a "Los Gabrieles"
Visita a "Los Gabrieles"iesdiegoangulo
 
Imprimanta
ImprimantaImprimanta
ImprimantacoroedMD
 
Hidroelektrik Santral Etkileri Raporu: Barhal Vadisi
Hidroelektrik Santral Etkileri Raporu: Barhal VadisiHidroelektrik Santral Etkileri Raporu: Barhal Vadisi
Hidroelektrik Santral Etkileri Raporu: Barhal VadisiTurkiye Su Meclisi
 
搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流jondynet
 
Hype vs. Reality: The AI Explainer
Hype vs. Reality: The AI ExplainerHype vs. Reality: The AI Explainer
Hype vs. Reality: The AI ExplainerLuminary Labs
 

Destaque (6)

Python在生物研究中的应用浅谈
Python在生物研究中的应用浅谈 Python在生物研究中的应用浅谈
Python在生物研究中的应用浅谈
 
Visita a "Los Gabrieles"
Visita a "Los Gabrieles"Visita a "Los Gabrieles"
Visita a "Los Gabrieles"
 
Imprimanta
ImprimantaImprimanta
Imprimanta
 
Hidroelektrik Santral Etkileri Raporu: Barhal Vadisi
Hidroelektrik Santral Etkileri Raporu: Barhal VadisiHidroelektrik Santral Etkileri Raporu: Barhal Vadisi
Hidroelektrik Santral Etkileri Raporu: Barhal Vadisi
 
搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流搜狐Pv insight(py)技术交流
搜狐Pv insight(py)技术交流
 
Hype vs. Reality: The AI Explainer
Hype vs. Reality: The AI ExplainerHype vs. Reality: The AI Explainer
Hype vs. Reality: The AI Explainer
 

Semelhante a 浮云脱水小说站的搭建

Static server介绍
Static server介绍Static server介绍
Static server介绍sun jamie
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践self study
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践rewinx
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践Frank Cai
 
[Modern Web 2016] 讓你的 PHP 開發流程再次潮起來
[Modern Web 2016] 讓你的 PHP 開發流程再次潮起來[Modern Web 2016] 讓你的 PHP 開發流程再次潮起來
[Modern Web 2016] 讓你的 PHP 開發流程再次潮起來Shengyou Fan
 
利用Signalr打造即時通訊@Tech day geek
利用Signalr打造即時通訊@Tech day geek利用Signalr打造即時通訊@Tech day geek
利用Signalr打造即時通訊@Tech day geekJohnson Gau
 
NodeJS基礎教學&簡介
NodeJS基礎教學&簡介NodeJS基礎教學&簡介
NodeJS基礎教學&簡介GO LL
 
高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用redhat9
 
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用redhat9
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践yiditushe
 
深入浅出Netty l.t
深入浅出Netty   l.t深入浅出Netty   l.t
深入浅出Netty l.toleone
 
AWS EC2 for beginner
AWS EC2 for beginnerAWS EC2 for beginner
AWS EC2 for beginnerazole Lai
 
Ajax Transportation Methods
Ajax Transportation MethodsAjax Transportation Methods
Ajax Transportation Methodsyiditushe
 
高性能并发Web服务器实现核心内幕
高性能并发Web服务器实现核心内幕高性能并发Web服务器实现核心内幕
高性能并发Web服务器实现核心内幕ideawu
 
Ajax新手快车道
Ajax新手快车道Ajax新手快车道
Ajax新手快车道yiditushe
 
Node.js长连接开发实践
Node.js长连接开发实践Node.js长连接开发实践
Node.js长连接开发实践longhao
 
富文本编辑器在互联网上的应用
富文本编辑器在互联网上的应用富文本编辑器在互联网上的应用
富文本编辑器在互联网上的应用luolonghao
 
Java华为面试题
Java华为面试题Java华为面试题
Java华为面试题yiditushe
 

Semelhante a 浮云脱水小说站的搭建 (20)

Berserk js
Berserk jsBerserk js
Berserk js
 
Static server介绍
Static server介绍Static server介绍
Static server介绍
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践高性能Web服务器Nginx及相关新技术的应用实践
高性能Web服务器Nginx及相关新技术的应用实践
 
[Modern Web 2016] 讓你的 PHP 開發流程再次潮起來
[Modern Web 2016] 讓你的 PHP 開發流程再次潮起來[Modern Web 2016] 讓你的 PHP 開發流程再次潮起來
[Modern Web 2016] 讓你的 PHP 開發流程再次潮起來
 
利用Signalr打造即時通訊@Tech day geek
利用Signalr打造即時通訊@Tech day geek利用Signalr打造即時通訊@Tech day geek
利用Signalr打造即時通訊@Tech day geek
 
NodeJS基礎教學&簡介
NodeJS基礎教學&簡介NodeJS基礎教學&簡介
NodeJS基礎教學&簡介
 
高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用高性能Web服务器nginx及相关新技术的应用
高性能Web服务器nginx及相关新技术的应用
 
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
ByPat博客出品-高性能Web服务器nginx及相关新技术的应用
 
Lucene 全文检索实践
Lucene 全文检索实践Lucene 全文检索实践
Lucene 全文检索实践
 
深入浅出Netty l.t
深入浅出Netty   l.t深入浅出Netty   l.t
深入浅出Netty l.t
 
AWS EC2 for beginner
AWS EC2 for beginnerAWS EC2 for beginner
AWS EC2 for beginner
 
Ajax Transportation Methods
Ajax Transportation MethodsAjax Transportation Methods
Ajax Transportation Methods
 
高性能并发Web服务器实现核心内幕
高性能并发Web服务器实现核心内幕高性能并发Web服务器实现核心内幕
高性能并发Web服务器实现核心内幕
 
Ajax新手快车道
Ajax新手快车道Ajax新手快车道
Ajax新手快车道
 
Node.js长连接开发实践
Node.js长连接开发实践Node.js长连接开发实践
Node.js长连接开发实践
 
富文本编辑器在互联网上的应用
富文本编辑器在互联网上的应用富文本编辑器在互联网上的应用
富文本编辑器在互联网上的应用
 
Java华为面试题
Java华为面试题Java华为面试题
Java华为面试题
 
摘星
摘星摘星
摘星
 

浮云脱水小说站的搭建

  • 2. 起因 一个寂寞的周末,作者手贱点开了这个“直播贴” 翻了十页以后发现贴吧直播贴完全是个 坑爹 的存在… 偷懒的程序员,做点什么吧!
  • 3. 想要的结果 最初的想法: 我需要一个脚本来替我完成抓取帖子中所有楼主的发言,并把它们存成一个静态页面来供阅读 我需要: 一个解析页面的工具(BeautifulSoup ) http://www.crummy.com/software/BeautifulSoup/
  • 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页面
  • 6. Thinking 效果页面 虽然已经初步达到了效果,能不能把这个东西升级成一个站点呢。 初步想法: 管理员(我)可以通过后台来添加帖子的原始url、分类、作者等信息。 另外用一个cron来负责根据后台添加的信息抓取生成html页面 项目到此分为两个: nowater: 负责被cron调用,从数据库查询出小说资源进行抓取工作 nowater_web: 负责前端web的展示,提供添加小说资源的后台
  • 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; }
  • 11. 后续问题&改进途径 小说源由管理员(我)手动添加效率太低 提供txt下载 对天涯社区的支持 改进途径: 允许用户直接添加原帖地址,并实时的展现抓取的过程 从抓取的html文件生成txt。 新建tianya_crawler.py
  • 12. 准备工作 Comet long-polling 基于ajax的长轮询 框架选择(Twisted)
  • 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 如果是已经存在的帖子,直接返回供阅读
  • 18. Thanks 希望Python在中国的应用越来越多 Enjoy coding! Author: piglei2007@gmail.com