下载糗事百科的内容_python版


Posted in Python onDecember 07, 2008
#coding:utf-8 import urllib.request 
import xml.dom.minidom 
import sqlite3 
import threading 
import time 
class logger(object): 
def log(self,*msg): 
for i in msg: 
print(i) 
Log = logger() 
Log.log('测试下') 
class downloader(object): 
def __init__(self,url): 
self.url = url 
def download(self): 
Log.log('开始下载',self.url) 
try: 
content = urllib.request.urlopen(self.url).read() 
#req = urllib.request.Request(url) 
#response = urllib.request.urlopen(req) 
#content = response.read() 
Log.log('下载完毕') 
return(content) 
except: 
Log.log('下载出错') 
return(None) 

class parser(object): 
def __init__(self,content): 
#获得根节点 
self.html = xml.dom.minidom.parseString(content) 
def parse(self): 
Log.log('开始提取数据') 
contents = {'content':'','url':[]} 
#获得div节点 
divs = self.html.getElementsByTagName('div') 
#获得content节点 
for div in divs: 
if div.hasAttribute('class') and \ 
div.getAttribute('class') == 'content': 
#获得糗事百科的内容 
textNode = div.childNodes[0] 
qContent = textNode.data 
#数据填充 
contents['content'] = qContent 
#获得上一糗事、下一糗事节点 
spans = self.html.getElementsByTagName('span') 
for span in spans: 
pspan = span.parentNode 
if pspan.tagName == 'a': 
#pspan为对应的链接,此时需要将对应的地址加入数据库 
url = pspan.getAttribute('href') 
qid = url[10:][:-4] 
#数据填充 
contents['url'].append(qid) 
Log.log('提取数据完毕') 
return(contents) 
def downloadPage(qid,db): 
url = 'http://www.qiushibaike.com/articles/'+str(qid)+'.htm' 
content = downloader(url).download() 
if content: 
contents = parser(content).parse() 
if contents['content']: 
db.updateContent(qid,contents['content']) 
for i in contents['url']: 
db.addQID(i) 
if len(contents['url']) == 2: 
db.updateStatus(qid,2) 
#下载池,表示同时允许下载的链接个数 
class downloaderPool(object): 
def __init__(self,maxLength=15): 
self.downloaders = [None]*maxLength 
self.downloadList = [] 
self.db = None 
def setDownloadList(self,downloadList): 
self.downloadList = list(set(self.downloadList+downloadList)) 
def setdb(self,db): 
self.db = db 
def daemon(self): 
#每隔一秒查询线程的状态,为非活动线程则设置为None 
Log.log('设置守护进程') 
for index,downloader in enumerate(self.downloaders): 
if downloader: 
if not downloader.isAlive(): 
Log.log('将下载器置空',index) 
self.downloaders[index] = None 
#检查线程池状态 
for index,downloader in enumerate(self.downloaders): 
if not downloader: 
qid = self.getQID() 
if qid: 
#创建线程 
t = threading.Thread(target=downloadPage,args=(qid,self.db)) 
self.downloaders[index] = t 
t.start() 
t.join() 
Log.log('设置下载器',index) 
#间隔一秒执行一次 
time.sleep(1) 
def getQID(self): 
try: 
tmp = self.downloadList[0] 
del self.downloadList[0] 
return(tmp) 
except: 
return(None) 
def beginDownload(self): 
#创建守护线程 
daemon = threading.Thread(target=self.daemon) 
daemon.setDaemon(True) 
daemon.start() 
daemon.join() 
def getDownloader(self): 
for index,downloader in enumerate(self.downloaders): 
if not downloader: 
return(index) 
return(None) 

ADD_Q_ID = 'insert into qiushibaike(id,success) values(?,?)' 
UPDATE_Q_CONTENT = 'update qiushibaike set content=? where id=?' 
UPDATE_Q_STATUS = 'update qiushibaike set success=? where id=?' 
Q_LIST = 'select id from qiushibaike where success=?' 
Q_LIST_BY_ID = 'select count(*) from qiushibaike where id=?' 
class dbConnect(object): 
""" 
create table qiushibaike( 
id,Integer 
content,Varchar 
success,Interger 
) 
#id表示糗事的ID 
#content表示糗事的内容 
#success表示是否下载成功,当该糗事内容下载完成,且获得上一页、下一页ID时表示下载完成 
1表示未完成 
2表示完成 
""" 
def __init__(self,dbpath='db.sqlite'): 
self.dbpath = dbpath 
def addQID(self,qid): 
Log.log('插入糗事百科',qid) 
#获得连接 
cn = sqlite3.connect(self.dbpath) 
c = cn.cursor() 
try: 
#添加内容并提交 
c.execute(ADD_Q_ID,(qid,1)) 
cn.commit() 
except: 
Log.log('添加ID出错',qid) 
#关闭连接 
c.close() 
cn.close() 
Log.log('插入成功') 
def updateContent(self,qid,content): 
Log.log('更新糗事百科',qid,content) 
#获得连接 
cn = sqlite3.connect(self.dbpath) 
c = cn.cursor() 
#添加内容并提交 
c.execute(UPDATE_Q_CONTENT,(content,qid)) 
cn.commit() 
#关闭连接 
c.close() 
cn.close() 
Log.log('更新成功') 
def updateStatus(self,qid,flag): 
Log.log('更新状态',qid,flag) 
#获得连接 
cn = sqlite3.connect(self.dbpath) 
c = cn.cursor() 
#添加内容并提交 
c.execute(UPDATE_Q_STATUS,(flag,qid)) 
cn.commit() 
#关闭连接 
c.close() 
cn.close() 
Log.log('更新状态成功') 
def getList(self,unDonloaded=1): 
Log.log('获得列表') 
l = [] 
#获得连接 
cn = sqlite3.connect(self.dbpath) 
c = cn.cursor() 
#获得数据 
c.execute(Q_LIST,(unDonloaded,)) 
rows = c.fetchall() 
for i in rows: 
l.append(i[0]) 
#关闭连接 
c.close() 
cn.close() 
Log.log('获得列表成功') 
return(l) 
class singleDownloader(object): 
def __init__(self): 
self.downloadList = [] 
def setdb(self,db): 
self.db = db 
def setDownloadList(self,downloadList): 
self.downloadList = list(set(self.downloadList+downloadList)) 
def beginDownload(self): 
for i in self.downloadList: 
downloadPage(i,self.db) 
def main(): 
db = dbConnect('db.sqlite') 
#dp = downloaderPool() 
#dp.setdb(db) 
sp = singleDownloader() 
sp.setdb(db) 
dp=sp 
unDownloadedList = db.getList() 
#当还有未下载的糗事时就要继续下载 
while(len(unDownloadedList)): 
#使用该列表填充下载池 
dp.setDownloadList(unDownloadedList) 
dp.beginDownload() 
time.sleep(1) 
#重置参数 
unDownloadedList = db.getList() 
if __name__ == '__main__': 
main()

代码是没问题的,可以正常运行,但是希望做到以下2方面:
1、多线程下载
2、代码分离度更高,跟面向对象
Python 相关文章推荐
python解析发往本机的数据包示例 (解析数据包)
Jan 16 Python
Python 异常处理实例详解
Mar 12 Python
Python写的Tkinter程序屏幕居中方法
Mar 10 Python
举例讲解Python面向对象编程中类的继承
Jun 17 Python
简单谈谈python中的lambda表达式
Jan 19 Python
如何利用Boost.Python实现Python C/C++混合编程详解
Nov 08 Python
Python编程中flask的简介与简单使用
Dec 28 Python
解决python web项目意外关闭,但占用端口的问题
Dec 17 Python
Pycharm最新激活码2019(推荐)
Dec 31 Python
sklearn线性逻辑回归和非线性逻辑回归的实现
Jun 09 Python
pycharm激活码2020最新分享适用pycharm2020最新版亲测可用
Nov 22 Python
解决TensorFlow训练模型及保存数量限制的问题
Mar 03 Python
python 参数列表中的self 显式不等于冗余
Dec 01 #Python
Python GAE、Django导出Excel的方法
Nov 24 #Python
Python类的基础入门知识
Nov 24 #Python
Python 连连看连接算法
Nov 22 #Python
python sqlobject(mysql)中文乱码解决方法
Nov 14 #Python
Python转码问题的解决方法
Oct 07 #Python
Python函数学习笔记
Oct 07 #Python
You might like
世界收音机发展史
2021/03/01 无线电
国内咖啡文化
2021/03/03 咖啡文化
php中如何判断一个网页请求是ajax请求还是普通请求
2013/08/10 PHP
php可生成缩略图的文件上传类实例
2014/12/17 PHP
typecho插件编写教程(三):保存配置
2015/05/28 PHP
laravel利用中间件防止未登录用户直接访问后台的方法
2019/09/30 PHP
jquery拖动插件(jquery.drag)使用介绍
2013/06/18 Javascript
JavaScript之IE的fireEvent方法详细解析
2013/11/20 Javascript
JavaScript初学者建议:不要去管浏览器兼容
2014/02/04 Javascript
javascript常见操作汇总
2014/09/03 Javascript
javacript使用break内层跳出外层循环分析
2015/01/12 Javascript
jquery实现标签支持图文排列带上下箭头按钮的选项卡
2015/03/14 Javascript
JQuery核心函数是什么及使用方法介绍
2016/05/03 Javascript
AngularJS 作用域详解及示例代码
2016/08/17 Javascript
浅谈javascript中的事件冒泡和事件捕获
2016/12/28 Javascript
JS实现经典的中国地区三级联动下拉菜单功能实例【测试可用】
2017/06/06 Javascript
easyui-datagrid开发实践(总结)
2017/08/02 Javascript
vue生成token保存在客户端localStorage中的方法
2017/10/25 Javascript
jQuery实现点击下拉框中的值累加到文本框中的方法示例
2017/10/28 jQuery
Node.js创建Web、TCP服务器
2017/12/05 Javascript
Easyui 去除jquery-easui tab页div自带滚动条的方法
2019/05/10 jQuery
jQuery控制input只能输入数字和两位小数的方法
2019/05/16 jQuery
原生JS无缝滑动轮播图
2019/10/22 Javascript
JavaScript或jQuery 获取option value值方法解析
2020/05/12 jQuery
在Vue中使用mockjs代码实例
2020/11/25 Vue.js
详解Python中列表和元祖的使用方法
2015/04/25 Python
python:print格式化输出到文件的实例
2018/05/14 Python
django自定义非主键自增字段类型详解(auto increment field)
2020/03/30 Python
学习Python需要哪些工具
2020/09/04 Python
Dodax奥地利:音乐、电影、书籍、玩具、电子产品等
2019/08/31 全球购物
韩国乐天网上商城:Lotte iMall
2021/02/03 全球购物
销售人员职业生涯规划范文
2014/03/01 职场文书
乡镇消防工作实施方案
2014/03/27 职场文书
沂蒙六姐妹观后感
2015/06/08 职场文书
2019年度开业庆典祝福语大全!
2019/07/05 职场文书
详解CSS中的特指度和层叠问题
2021/07/15 HTML / CSS