下载糗事百科的内容_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实现从订阅源下载图片的方法
Mar 11 Python
python中range()与xrange()用法分析
Sep 21 Python
Python探索之创建二叉树
Oct 25 Python
Python3 使用cookiejar管理cookie的方法
Dec 28 Python
Python3实现取图片中特定的像素替换指定的颜色示例
Jan 24 Python
pycharm重命名文件的方法步骤
Jul 29 Python
解决Python计算矩阵乘向量,矩阵乘实数的一些小错误
Aug 26 Python
python 视频逐帧保存为图片的完整实例
Dec 10 Python
Python3 全自动更新已安装的模块实现
Jan 06 Python
关于Python3的import问题(pycharm可以运行命令行import错误)
Nov 18 Python
python字符串拼接+和join的区别详解
Dec 03 Python
Python各协议下socket黏包问题原理
Apr 12 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
谈谈新手如何学习PHP
2006/12/23 PHP
PHP中图片等比缩放的实例
2013/03/24 PHP
Node.js插件的正确编写方式
2014/08/03 Javascript
jQuery模拟黑客帝国矩阵效果实例
2015/06/28 Javascript
详解JavaScript基于面向对象之继承
2015/12/13 Javascript
vue.js中$watch的用法示例
2016/10/04 Javascript
JavaScript省市级联下拉菜单实例
2017/02/14 Javascript
node.js连接MongoDB数据库的2种方法教程
2017/05/17 Javascript
关于redux-saga中take使用方法详解
2018/02/27 Javascript
浅谈在node.js进入文件目录的问题
2018/05/13 Javascript
JavaScript设计模式之模板方法模式原理与用法示例
2018/08/07 Javascript
在Vue中使用axios请求拦截的实现方法
2018/10/25 Javascript
Vue实现购物车的全选、单选、显示商品价格代码实例
2019/05/06 Javascript
详解简单易懂的 ES6 Iterators 指南和示例
2019/09/24 Javascript
浅谈Vue为什么不能检测数组变动
2019/10/14 Javascript
vue 通过 Prop 向子组件传递数据的实现方法
2020/10/30 Javascript
Flask数据库迁移简单介绍
2017/10/24 Python
python编写Logistic逻辑回归
2020/12/30 Python
Python获取系统所有进程PID及进程名称的方法示例
2018/05/24 Python
Python爬虫框架Scrapy常用命令总结
2018/07/26 Python
PyQt5实现QLineEdit添加clicked信号的方法
2019/06/25 Python
python 实现GUI(图形用户界面)编程详解
2019/07/17 Python
Python自动化完成tb喵币任务的操作方法
2019/10/30 Python
在Python中通过threshold创建mask方式
2020/02/19 Python
python实现简单的购物程序代码实例
2020/03/03 Python
Python selenium爬取微博数据代码实例
2020/05/22 Python
Python with语句用法原理详解
2020/07/03 Python
Python打印不合法的文件名
2020/07/31 Python
aec加密 php_php aes加密解密类(兼容php5、php7)
2021/03/14 PHP
雅诗兰黛旗下走天然植物路线的彩妆品牌:Prescriptives
2016/08/14 全球购物
个人简历中的自我评价范例
2013/10/29 职场文书
酒店人事专员岗位职责
2013/12/19 职场文书
党的群众路线教育实践活动个人对照检查材料(公安)
2014/11/05 职场文书
2014年教研员工作总结
2014/12/23 职场文书
医生辞职信范文
2015/03/02 职场文书
2015年大学生党员承诺书
2015/04/27 职场文书