下载糗事百科的内容_python版

  1.  #coding:utf-8
  2. import urllib.request
  3. import xml.dom.minidom
  4. import sqlite3
  5. import threading
  6. import time
  7. class logger(object):
  8.     def log(self,*msg):
  9.         for i in msg:
  10.             print(i)
  11. Log = logger()
  12. Log.log('测试下')
  13. class downloader(object):
  14.     
  15.     def __init__(self,url):
  16.         self.url = url
  17.     
  18.     def download(self):
  19.         Log.log('开始下载',self.url)
  20.         try:
  21.             content = urllib.request.urlopen(self.url).read()
  22.             #req = urllib.request.Request(url)
  23.             #response = urllib.request.urlopen(req)
  24.             #content = response.read()
  25.             Log.log('下载完毕')
  26.             return(content)   
  27.         except:
  28.             Log.log('下载出错')
  29.             return(None)
  30.        
  31.             
  32. class parser(object):
  33.     
  34.     def __init__(self,content):
  35.         #获得根节点
  36.         self.html = xml.dom.minidom.parseString(content)
  37.     
  38.     def parse(self):
  39.         Log.log('开始提取数据')
  40.         contents = {'content':'','url':[]}
  41.         #获得div节点
  42.         divs = self.html.getElementsByTagName('div')
  43.         #获得content节点
  44.         for div in divs:
  45.             if div.hasAttribute('class'and /
  46.                div.getAttribute('class') == 'content':
  47.                #获得糗事百科的内容
  48.                textNode = div.childNodes[0]
  49.                qContent = textNode.data
  50.                #数据填充
  51.                contents['content'] = qContent
  52.         
  53.         #获得上一糗事、下一糗事节点
  54.         spans = self.html.getElementsByTagName('span')
  55.         for span in spans:
  56.             pspan = span.parentNode
  57.             if pspan.tagName == 'a':
  58.                 #pspan为对应的链接,此时需要将对应的地址加入数据库
  59.                 url = pspan.getAttribute('href')
  60.                 qid = url[10:][:-4]
  61.                 #数据填充
  62.                 contents['url'].append(qid)
  63.         Log.log('提取数据完毕')
  64.         return(contents)
  65. def downloadPage(qid,db):
  66.     url = 'http://www.qiushibaike.com/articles/'+str(qid)+'.htm'
  67.     content = downloader(url).download()
  68.     if content:
  69.         contents = parser(content).parse()
  70.         if contents['content']:
  71.             db.updateContent(qid,contents['content'])
  72.         for i in contents['url']:
  73.             db.addQID(i)
  74.         if len(contents['url']) == 2:
  75.             db.updateStatus(qid,2)
  76. #下载池,表示同时允许下载的链接个数
  77. class downloaderPool(object):
  78.     def __init__(self,maxLength=15):
  79.         self.downloaders = [None]*maxLength
  80.         self.downloadList = []
  81.         self.db = None
  82.     
  83.     def setDownloadList(self,downloadList):
  84.         self.downloadList = list(set(self.downloadList+downloadList))
  85.     
  86.     def setdb(self,db):
  87.         self.db = db
  88.     
  89.     def daemon(self):
  90.         #每隔一秒查询线程的状态,为非活动线程则设置为None
  91.         Log.log('设置守护进程')
  92.         for index,downloader in enumerate(self.downloaders):
  93.             if downloader:
  94.                 if not downloader.isAlive():
  95.                     Log.log('将下载器置空',index)
  96.                     self.downloaders[index] = None
  97.         
  98.         #检查线程池状态
  99.         for index,downloader in enumerate(self.downloaders):
  100.             if not downloader:
  101.                 qid = self.getQID()
  102.                 if qid:
  103.                     #创建线程
  104.                     t = threading.Thread(target=downloadPage,args=(qid,self.db))   
  105.                     self.downloaders[index] = t
  106.                     t.start()
  107.                     t.join()
  108.                     Log.log('设置下载器',index)
  109.         #间隔一秒执行一次
  110.         time.sleep(1)            
  111.     
  112.     def getQID(self):
  113.         try:
  114.             tmp = self.downloadList[0]
  115.             del self.downloadList[0]
  116.             return(tmp)
  117.         except:
  118.             return(None)
  119.         
  120.     def beginDownload(self):
  121.         #创建守护线程
  122.         daemon = threading.Thread(target=self.daemon)
  123.         daemon.setDaemon(True)
  124.         daemon.start()
  125.         daemon.join()          
  126.                     
  127.     def getDownloader(self):
  128.         for index,downloader in enumerate(self.downloaders):
  129.             if not downloader:
  130.                 return(index)
  131.         return(None)
  132. ADD_Q_ID = 'insert into qiushibaike(id,success) values(?,?)'
  133. UPDATE_Q_CONTENT = 'update qiushibaike set content=? where id=?'
  134. UPDATE_Q_STATUS = 'update qiushibaike set success=? where id=?'
  135. Q_LIST = 'select id from qiushibaike where success=?'
  136. Q_LIST_BY_ID = 'select count(*) from qiushibaike where id=?'
  137. class dbConnect(object):
  138.     """
  139.     create table qiushibaike(
  140.     id,Integer
  141.     content,Varchar
  142.     success,Interger
  143.     )
  144.     #id表示糗事的ID
  145.     #content表示糗事的内容
  146.     #success表示是否下载成功,当该糗事内容下载完成,且获得上一页、下一页ID时表示下载完成
  147.             1表示未完成
  148.             2表示完成
  149.     """
  150.     def __init__(self,dbpath='db.sqlite'):
  151.         self.dbpath = dbpath
  152.     
  153.     def addQID(self,qid):
  154.         Log.log('插入糗事百科',qid)
  155.         #获得连接
  156.         cn = sqlite3.connect(self.dbpath)
  157.         c = cn.cursor()
  158.         
  159.         try:
  160.             #添加内容并提交
  161.             c.execute(ADD_Q_ID,(qid,1))
  162.             cn.commit()
  163.         except:
  164.             Log.log('添加ID出错',qid)
  165.         
  166.         #关闭连接            
  167.         c.close()
  168.             
  169.         cn.close()
  170.         Log.log('插入成功')
  171.     
  172.     def updateContent(self,qid,content):
  173.         Log.log('更新糗事百科',qid,content)
  174.         #获得连接
  175.         cn = sqlite3.connect(self.dbpath)
  176.         c = cn.cursor()
  177.         #添加内容并提交
  178.         c.execute(UPDATE_Q_CONTENT,(content,qid))
  179.         cn.commit()
  180.         #关闭连接
  181.         c.close()
  182.         cn.close()
  183.         Log.log('更新成功')
  184.     
  185.     def updateStatus(self,qid,flag):
  186.         Log.log('更新状态',qid,flag)
  187.         #获得连接
  188.         cn = sqlite3.connect(self.dbpath)
  189.         c = cn.cursor()
  190.         #添加内容并提交
  191.         c.execute(UPDATE_Q_STATUS,(flag,qid))
  192.         cn.commit()
  193.         #关闭连接
  194.         c.close()
  195.         cn.close()
  196.         Log.log('更新状态成功')
  197.     
  198.     def getList(self,unDonloaded=1):
  199.         Log.log('获得列表')
  200.         l = []
  201.         #获得连接
  202.         cn = sqlite3.connect(self.dbpath)
  203.         c = cn.cursor()
  204.         #获得数据
  205.         c.execute(Q_LIST,(unDonloaded,))
  206.         rows = c.fetchall()
  207.         
  208.         for i in rows:
  209.             l.append(i[0])
  210.         #关闭连接
  211.         c.close()
  212.         cn.close()
  213.         
  214.         Log.log('获得列表成功')
  215.         return(l)
  216. class singleDownloader(object):
  217.     def __init__(self):
  218.         self.downloadList = []
  219.     
  220.     def setdb(self,db):
  221.         self.db = db
  222.     
  223.     def setDownloadList(self,downloadList):
  224.         self.downloadList = list(set(self.downloadList+downloadList))
  225.         
  226.     def beginDownload(self):
  227.         for i in self.downloadList:
  228.             downloadPage(i,self.db)
  229.     
  230. def main():
  231.     db = dbConnect('db.sqlite')
  232.     #dp = downloaderPool()
  233.     #dp.setdb(db)
  234.     sp = singleDownloader()
  235.     sp.setdb(db)
  236.     
  237.     dp=sp
  238.     
  239.     unDownloadedList = db.getList()
  240.     #当还有未下载的糗事时就要继续下载
  241.     while(len(unDownloadedList)):
  242.         #使用该列表填充下载池
  243.         dp.setDownloadList(unDownloadedList)
  244.         
  245.         dp.beginDownload()
  246.         
  247.         time.sleep(1)
  248.         #重置参数
  249.         unDownloadedList = db.getList()
  250. if __name__ == '__main__':
  251.     main()
代码是没问题的,可以正常运行,但是希望做到以下2方面:
1、多线程下载
2、代码分离度更高,跟面向对象

各位看家有什么好想法,贴出来看看。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值