最近我突然对网络爬虫开窍了,真正做起来的时候发现并不算太难,都怪我以前有点懒,不过近两年编写了一些程序,手感积累了一些肯定也是因素,总之,还是惭愧了。好了,说正题,我把这两天做爬虫的过程中遇到的问题总结一下:

  需求:做一个爬虫,爬取一个网站上所有的图片(只爬大图,小图标就略过)

  思路:1、获取网站入口,这个入口网页上有很多图片集合入口,进入这些图片集合就能看到图片链接了,所以爬取的深度为2,比较简单;2、各个子图片集合内所包含的图片链接有两种形式:一种是绝对图片路径(直接下载即可),另一种的相对图片路径(需要自行拼接当前网页路径)。总之这些子图集合的表现形式简单,没有考虑更复杂的情况。3、在爬取的过程中保存已成功爬取的路径,防止每次爬取都执行重复的任务,当然,当每次启动时要首先加载该历史数据库,剩下的就是细节了。

  快速链接:

2.1 日志系统

2.2 记录访问历史

2.3 异常处理

2.4 网页自动编码判断

2.5 远程主机重置链接(Errno 10054)

2.6 使用BeautifulSoup来分析网页

一、全部代码

  直接先来代码,再详细说优化的过程和内容吧:

  1. __author__ = 'KLH'
  2. # -*- coding:utf-8 -*-
  3.  
  4. import urllib
  5. import urllib2
  6. import chardet
  7. import re
  8. import os
  9. import time
  10. from myLogger import *
  11.  
  12. # 网络蜘蛛
  13. class Spider:
  14.  
  15. # 类初始化
  16. def __init__(self):
  17. self.contentFolder = u"抓取内容"
  18. self.dbName = "url.db"
  19. self.createFolder(self.contentFolder)
  20. self.urlDB = set()
  21.  
  22. # 获取URL数据库以获取爬过的网页地址
  23. def loadDatabase(self):
  24. isExists = os.path.exists(self.dbName)
  25. if not isExists:
  26. logging.info(u"创建URL数据库文件:'" + self.dbName + u"'")
  27. f = open(self.dbName, 'w+')
  28. f.write("#Create time: " + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) + '\n')
  29. f.close()
  30. return
  31. db = open(self.dbName, 'r')
  32. for line in db.readlines():
  33. if not line.startswith('#'):
  34. self.urlDB.add(line.strip('\n'))
  35. db.close()
  36. logging.info(u"URL数据库加载完成!")
  37.  
  38. # 追加数据库文件
  39. def writeToDatabase(self, url):
  40. db = open(self.dbName, 'a')
  41. db.write(url + '\n')
  42. db.close()
  43.  
  44. # 处理路径名称中的空格字符
  45. def getPathName(self, pathName):
  46. newName = ""
  47. subName = pathName.split()
  48. i = 0
  49. while i < len(subName) - 1:
  50. newName = newName + subName[i]
  51. i = i + 1
  52. return newName
  53.  
  54. # 获取索引页面的内容
  55. def getPage(self, pageURL, second):
  56. try:
  57. headers = {'User-agent' : 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0'}
  58. request = urllib2.Request(pageURL, headers = headers)
  59. response = urllib2.urlopen(request, timeout = second)
  60. data = response.read()
  61. response.close()
  62. return data.decode('gbk'), True
  63. except urllib2.HTTPError,e: #HTTPError必须排在URLError的前面
  64. logging.error("HTTPError code:" + str(e.code) + " - Content:" + e.read())
  65. return "", False
  66. except urllib2.URLError, e:
  67. logging.error("URLError reason:" + str(e.reason) + " - " + str(e))
  68. return "", False
  69. except Exception, e:
  70. logging.error(u"获取网页失败:" + str(e))
  71. return "", False
  72.  
  73. # 获取索引界面所有子页面信息,list格式
  74. def getContents(self, pageURL, second):
  75. contents = []
  76. page, succeed = self.getPage(pageURL, second)
  77. if succeed:
  78. # 这里的正则表达式很重要,决定了第一步的抓取内容:
  79. pattern = re.compile('<tr>.*?<a href="(.*?)".*?<b>(.*?)</b>.*?</tr>',re.S)
  80. items = re.findall(pattern,page)
  81. for item in items:
  82. contents.append([item[0],item[1]])
  83. contents.sort()
  84. return contents
  85.  
  86. # 获取页面所有图片
  87. def getAllImgURL(self, infoURL):
  88. images = []
  89. succeed = True
  90. try:
  91. headers = {'User-agent' : 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0'}
  92. request = urllib2.Request(infoURL, headers = headers)
  93. data = urllib2.urlopen(request).read()
  94. chardet1 = chardet.detect(data) # 自动判断网页编码
  95. page = data.decode(str(chardet1['encoding']))
  96.  
  97. # 第一种解码格式:
  98. pattern = re.compile('<option value="(.*?)">(.*?)</option>')
  99. items = re.findall(pattern, page)
  100. # item[0]为图片URL尾部,item[1]为图片名称
  101. for item in items:
  102. if item.startswith('http://'):
  103. imageURL = item[0]
  104. if imageURL in self.urlDB:
  105. logging.info(u"获得图片URL(曾被访问,跳过):" + imageURL)
  106. else:
  107. logging.info(u"获得图片URL:" + imageURL)
  108. images.append(imageURL)
  109. else:
  110. imageURL = infoURL + item[0]
  111. if imageURL in self.urlDB:
  112. logging.info(u"获得图片URL(曾被访问,跳过):" + imageURL)
  113. else:
  114. logging.info(u"获得图片URL:" + imageURL)
  115. images.append(imageURL)
  116.  
  117. # 第二种解码格式
  118. pattern = re.compile('<IMG src="(.*?)".*?>')
  119. items = re.findall(pattern, page)
  120. # item为图片URL
  121. for item in items:
  122. if item.startswith('http://'):
  123. if item in self.urlDB:
  124. logging.info(u"获得图片URL(曾被访问,跳过):" + item)
  125. else:
  126. logging.info(u"获得图片URL:" + item)
  127. images.append(item)
  128.  
  129. except Exception, e:
  130. logging.warning(u"在获取子路径图片列表时出现异常:" + str(e))
  131. succeed = False
  132. return images, succeed
  133.  
  134. # 保存所有图片
  135. def saveImgs(self, images, name):
  136. logging.info(u'发现"' + name + u'"共有' + str(len(images)) + u"张照片")
  137. allSucceed = True
  138. for imageURL in images:
  139. splitPath = imageURL.split('/')
  140. fTail = splitPath.pop()
  141. fileName = name + "/" + fTail
  142. logging.info(u"开始准备保存图片(超时设置:120秒):" + imageURL)
  143. startTime = time.time()
  144. succeed = self.saveImg(imageURL, fileName, 120)
  145. spanTime = time.time() - startTime
  146. if succeed:
  147. logging.info(u"保存图片完成(耗时:" + str(spanTime) + u"秒):" + fileName)
  148. # 保存文件存储记录
  149. self.urlDB.add(imageURL)
  150. self.writeToDatabase(imageURL)
  151. else:
  152. logging.warning(u"保存图片失败(耗时:" + str(spanTime) + u"秒):" + imageURL)
  153. allSucceed = False
  154. # 为了防止网站封杀,这里暂停1秒
  155. time.sleep(1)
  156. return allSucceed
  157.  
  158. # 传入图片地址,文件名,超时时间,保存单张图片
  159. def saveImg(self, imageURL, fileName, second):
  160. try:
  161. headers = {'User-agent' : 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0'}
  162. request = urllib2.Request(imageURL, headers = headers)
  163. u = urllib2.urlopen(request, timeout = second)
  164. data = u.read()
  165. f = open(fileName, 'wb')
  166. f.write(data)
  167. f.close()
  168. u.close()
  169. return True
  170. except urllib2.HTTPError,e: #HTTPError必须排在URLError的前面
  171. logging.error("HTTPError code:" + str(e.code) + " - Content:" + e.read())
  172. return False
  173. except urllib2.URLError, e:
  174. logging.error("URLError reason:" + str(e.reason) + " - " + str(e))
  175. return False
  176. except Exception, e:
  177. logging.error(u"保存图片失败:" + str(e))
  178. return False
  179.  
  180. # 创建新目录
  181. def createFolder(self, path):
  182. path = path.strip()
  183. # 判断路径是否存在
  184. isExists=os.path.exists(path)
  185. # 判断结果
  186. if not isExists:
  187. # 如果不存在则创建目录
  188. logging.info(u"创建文件夹:'" + path + u"'")
  189. # 创建目录操作函数
  190. os.makedirs(path)
  191. return True
  192. else:
  193. # 如果目录存在则不创建,并提示目录已存在
  194. logging.info(u"名为'" + path + u"'的文件夹已经存在,跳过")
  195. return False
  196.  
  197. # 获取的首页地址
  198. def savePageInfo(self, pageURL):
  199. logging.info(u"准备获取网页内容(超时设置:60秒):" + pageURL)
  200. contents = self.getContents(pageURL, 60)
  201. logging.info(u"网页内容获取完成,子路径个数:" + str(len(contents)))
  202. index = 1
  203. for item in contents:
  204. #(1)item[0]子路径URL, item[1]子路径名称
  205. folderURL = item[0]
  206. folderName = self.contentFolder + '\\' + str(index) + "-" + self.getPathName(item[1])
  207. self.createFolder(folderName)
  208. index = index + 1
  209.  
  210. #(2)判断链接头部合法性和重复性
  211. if not folderURL.startswith('http://'):
  212. folderURL = pageURL + folderURL
  213. if folderURL in self.urlDB:
  214. logging.info(u'"' + folderName + u'"的链接地址(已访问,跳过)为:' + folderURL)
  215. continue
  216. else:
  217. logging.info(u'"' + folderName + u'"的链接地址为:' + folderURL)
  218.  
  219. #(3)获取图片URL列表,成功则保存图片
  220. images, succeed = self.getAllImgURL(folderURL)
  221. if succeed:
  222. succeed = self.saveImgs(images, folderName)
  223. if succeed:
  224. self.urlDB.add(folderURL)
  225. self.writeToDatabase(folderURL)
  226.  
  227. # 初始化系统日志存储
  228. InitLogger()
  229. # 传入初始网页地址,自动启动爬取图片:
  230. spider = Spider()
  231. spider.loadDatabase()
  232. spider.savePageInfo('http://365.tw6000.com/xtu/')
  233. logging.info(u"全部网页内容爬取完成!程序退出。")

查看全部代码

二、问题历史

  在上面的代码中有不少的细节是优化解决过的,相关的知识点如下:

2.1 日志系统

  Python的日志系统是相当的不错,非常的方便,详细的资料可以参考Python官方文档,或者上一篇博文也是提到过的:《Python中的日志管理Logging模块》,应用到我这个爬虫这里的代码就是myLogger.py模块了,用起来很方便:

  1. __author__ = 'KLH'
  2. # -*- coding:utf-8 -*-
  3.  
  4. import logging
  5. import time
  6.  
  7. def InitLogger():
  8. logFileName = 'log_' + time.strftime("%Y%m%d%H%M%S", time.localtime(time.time())) + '.txt'
  9. logging.basicConfig(level=logging.DEBUG,
  10. format='[%(asctime)s][%(filename)s:%(lineno)d][%(levelname)s] - %(message)s',
  11. filename=logFileName,
  12. filemode='w')
  13.  
  14. # 定义一个StreamHandler将INFO级别以上的信息打印到控制台
  15. console = logging.StreamHandler()
  16. console.setLevel(logging.INFO)
  17. formatter = logging.Formatter('[%(asctime)s][%(filename)s:%(lineno)d][%(levelname)s] - %(message)s')
  18. console.setFormatter(formatter)
  19. logging.getLogger('').addHandler(console)

查看myLogger.py

  注意在爬虫的代码执行前调用一下该函数:

  1. from myLogger import *
    # 初始化系统日志存储
  2. InitLogger()

  日志调用和打印的结果如下:

  1. logging.info(u"准备获取网页内容(超时设置:60秒):" + pageURL)
  2.  
  3. #打印结果如下:
  4. [2015-11-09 22:35:02,976][spider2.py:182][INFO] - 准备获取网页内容(超时设置:60秒):http://365.XXXXX.com/xtu/

2.2 记录访问历史

  这里记录URL的访问历史是为了防止执行重复任务,在内存中保持一个Set就能满足需求,在磁盘上可以简单的保存成一个TXT文件,每个URL保存成一行即可。所以这里是逻辑顺序应该是在初始化时创建一个Set用来保存访问历史,任务执行之前从数据库中加载访问历史,如果是首次运行尚未创建数据库还需要进行一次创建操作。然后就好办了,每次完成一个URL的访问就保存一下访问记录。相关代码如下:

  1. # 类初始化
  2. def __init__(self):
  3. self.contentFolder = u"抓取内容"
  4. self.dbName = "url.db"          # 1、定义数据库文件名
  5. self.createFolder(self.contentFolder)   # 2、创建内容存储目录
  6. self.urlDB = set()             # 3、创建内存数据库
  7.  
  8. # 获取URL数据库以获取爬过的网页地址
  9. def loadDatabase(self):
  10. isExists = os.path.exists(self.dbName)  # 4、首先判断是否是首次运行,如果数据库文件不存在则创建一下
  11. if not isExists:
  12. logging.info(u"创建URL数据库文件:'" + self.dbName + u"'")
  13. f = open(self.dbName, 'w+')
  14. f.write("#Create time: " + time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(time.time())) + '\n')
  15. f.close()
  16. return
  17. db = open(self.dbName, 'r')         # 5、从磁盘中加载数据库
  18. for line in db.readlines():
  19. if not line.startswith('#'):
  20. self.urlDB.add(line.strip('\n'))
  21. db.close()
  22. logging.info(u"URL数据库加载完成!")
  23.  
  24. # 追加数据库文件
  25. def writeToDatabase(self, url):         # 6、在系统运行过程中,如需记录日志,追加日志内容即可
  26. db = open(self.dbName, 'a')
  27. db.write(url + '\n')
  28. db.close()

  有了上面的代码,在记录日志过程中就很方便了:

  1. succeed = self.saveImgs(images, folderName)
  2. if succeed:
  3. self.urlDB.add(folderURL)
  4. self.writeToDatabase(folderURL)

2.3 异常处理

  访问网络资源不可避免的会有很多异常情况,要处理这些异常情况才能稳定运行,Python的异常处理很简单,请参考如下获取网页的代码段:

  1. # 获取索引页面的内容
  2. def getPage(self, pageURL, second):
  3. try:
  4. request = urllib2.Request(pageURL)
  5. response = urllib2.urlopen(request, timeout = second)
  6. data = response.read()
  7. return data.decode('gbk'), True
  8. except urllib2.HTTPError,e: # HTTPError必须排在URLError的前面
  9. logging.error("HTTPError code:" + str(e.code) + " - Content:" + e.read())
  10. return "", False
  11. except urllib2.URLError, e:
  12. logging.error("URLError reason:" + str(e.reason) + " - " + str(e))
  13. return "", False
  14. except Exception, e:       # 其他所有类型的异常
  15. logging.error(u"获取网页失败:" + str(e))
  16. return "", False       # 这里返回两个值方便判断

2.4 网页自动编码判断

  昨天在爬取网页的过程中突然发现,有的页面居然说编码不能通过utf-8进行解析,我看了看有的网页确实不是utf-8编码的,那怎么办呢?怎么才能自动进行解码?从网上可以搜索到一个Python的开源库很好用,叫做chardet,默认Python2.7是不带的需要下载,比如我下载的是:chardet-2.3.0.tar.gz

  有了这个压缩包解压出来cahrdet子文件夹拷贝到:C:\Python27\Lib\site-packages目录下即可。下面看看用法实例:

  1. import chardet
  2.  
  3. # 获取页面所有图片
  4. def getAllImgURL(self, infoURL):
  5. images = []
  6. succeed = True
  7. try:
  8. data = urllib2.urlopen(infoURL).read()  # 1、先获取网页内容
  9. chardet1 = chardet.detect(data)    # 2、再调用该模块的方法自动判断网页编码
  10. page = data.decode(str(chardet1['encoding'])) # 3、注意,得到的chardet1是一个字典类似于:{'confidence': 0.98999999999999999, 'encoding': 'GB2312'}
  11.  
  12. # 第一种解码格式:
  13. pattern = re.compile('<option value="(.*?)">(.*?)</option>')
  14. items = re.findall(pattern, page)
  15. # item[0]为图片URL尾部,item[1]为图片名称
  16. for item in items:
  17. imageURL = infoURL + item[0]
  18. if imageURL in self.urlDB:
  19. logging.info(u"获得图片URL(曾被访问,跳过):" + imageURL)
  20. else:
  21. logging.info(u"获得图片URL:" + imageURL)
  22. images.append(imageURL)
  23.  
  24. # 第二种解码格式
  25. pattern = re.compile('<IMG src="(.*?)".*?>')
  26. items = re.findall(pattern, page)
  27. # item为图片URL
  28. for item in items:
  29. if item.startswith('http://'):    # 4、这里也注意一下,在这种网页中相对路径的图片都是插图之类的小图片不需要下载,所以过滤掉了。
  30. if item in self.urlDB:
  31. logging.info(u"获得图片URL(曾被访问,跳过):" + item)
  32. else:
  33. logging.info(u"获得图片URL:" + item)
  34. images.append(item)
  35.  
  36. except Exception, e:
  37. logging.warning(u"在获取子路径图片列表时出现异常:" + str(e))
  38. succeed = False
  39. return images, succeed

2.5 远程主机重置链接(Errno 10054)

  在今天的爬取过程中我发现了一个问题,爬到后面的内容都出错了,错误信息参见如下:

  1. [2015-11-09 23:48:51,082][spider2.py:130][INFO] - 开始准备保存图片(超时设置:300秒):http://xz1.XXXX.com/st/st-06/images/009.jpg
  2. [2015-11-09 23:48:55,095][spider2.py:160][ERROR] - 保存图片失败:[Errno 10054]
  3. [2015-11-09 23:48:55,096][spider2.py:140][WARNING] - 保存图片失败(耗时:4.01399993896秒):http://xz1.XXXX.com/st/st-06/images/009.jpg
  4. [2015-11-09 23:48:55,098][spider2.py:130][INFO] - 开始准备保存图片(超时设置:300秒):http://xz1.XXXX.com/st/st-06/images/010.jpg
  5. [2015-11-09 23:48:56,576][spider2.py:160][ERROR] - 保存图片失败:[Errno 10054]
  6. [2015-11-09 23:48:56,578][spider2.py:140][WARNING] - 保存图片失败(耗时:1.48000001907秒):http://xz1.XXXX.com/st/st-06/images/010.jpg

  可以看到都在报这个错误代码,网上一查,发现有很多同学已经遇到过了,请参考知乎上的讨论:http://www.zhihu.com/question/27248551

  从网上讨论的结果来看,可以肯定的是直接原因在于“远程主机主动关闭了当前链接”,而根本原因则在于:网站启用了反爬虫的策略,也就是说我的爬虫爬的过快并且被发现不是真正的浏览器浏览了。怎么办了?针对这两个原因逐个处理,一是伪装成浏览器,二是不要访问的过快,三是每次访问完成都关闭链接。相关代码如下:

  1. # 传入图片地址,文件名,超时时间,保存单张图片
  2. def saveImg(self, imageURL, fileName, second):
  3. try:
  4. headers = {'User-agent' : 'Mozilla/5.0 (Windows NT 6.2; WOW64; rv:22.0) Gecko/20100101 Firefox/22.0'}  # 1、这里构造一个浏览器的头部
  5. request = urllib2.Request(imageURL, headers = headers)
  6. u = urllib2.urlopen(request, timeout = second)     # 2、这里的超时设置timeout不要太长
  7. data = u.read()
  8. f = open(fileName, 'wb')
  9. f.write(data)
  10. f.close()
  11. u.close()    # 3、注意这里的链接要主动调用一下关闭
  12. return True
  13. except urllib2.HTTPError,e: #HTTPError必须排在URLError的前面
  14. logging.error("HTTPError code:" + str(e.code) + " - Content:" + e.read())
  15. return False
  16. except urllib2.URLError, e:
  17. logging.error("URLError reason:" + str(e.reason) + " - " + str(e))
  18. return False
  19. except Exception, e:
  20. logging.error(u"保存图片失败:" + str(e))
  21. return False  # 4、注意调用完这个函数之后再time.sleep(1)一下,防止过快访问被发现了,呵呵

 2.6 使用BeautifulSoup来分析网页

   使用正则表达式来匹配网页中的字段确实是太费劲了。用BeautifulSoup就省力多了,功能很强大:

  1. soup = BeautifulSoup(page_data, 'lxml')
  2. entries = soup.find_all(src=re.compile('.jpg'), border='')    # 找到所有字段为src正则匹配的标签内容,同时增加一个约束条件是border=‘0’

  Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,如果我们不安装它,则 Python 会使用 Python默认的解析器,lxml 解析器更加强大,速度更快,推荐安装。

Python爬虫(图片)编写过程中遇到的问题的更多相关文章

  1. Selenium2学习-018-WebUI自动化实战实例-016-自动化脚本编写过程中的登录验证码问题

    日常的 Web 网站开发的过程中,为提升登录安全或防止用户通过脚本进行黄牛操作(宇宙最贵铁皮天朝魔都的机动车牌照竞拍中),很多网站在登录的时候,添加了验证码验证,而且验证码的实现越来越复杂,对其进行脚 ...

  2. 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览

    ### 利用Gulp实现JSDoc 3的文档编写过程中的实时解析和效果预览 http://segmentfault.com/a/1190000002583569

  3. 【lombok】使用lombok注解,在代码编写过程中可以调用到get/set方法,但是在编译的时候无法通过,提示找不到get/set方法

    错误如题:使用lombok注解,在代码编写过程中可以调用到get/set方法,但是在编译的时候无法通过,提示找不到get/set方法 报错如下: 解决方法: 1.首先查看你的lombok插件是否下载安 ...

  4. python爬虫爬取内容中,-xa0,-u3000的含义

    python爬虫爬取内容中,-xa0,-u3000的含义 - CSDN博客 https://blog.csdn.net/aiwuzhi12/article/details/54866310

  5. appium+python+android+HTMLTestRunner使用过程中的问题

    1:问:appium客户端刚发布了一版新的,我想升级可以吗?答:建议对于刚发布的新版本不要立即升级,因为客户端每升级一版它肯定会去增加和删减一些语句.所以不建议立即升级.    应该先采取调研的态度看 ...

  6. [持续更新] Python学习、使用过程中遇见的非代码层面知识(想不到更好的标题了 T_T)

    写在前面: 这篇博文记录的不是python代码.数据结构.算法相关的内容,而是在学习.使用过程中遇见的一些没有技术含量,但有时很令人抓耳挠腮的小东西.比如:python内置库怎么看.python搜索模 ...

  7. python 爬虫001-http请求过程

    HTTP 请求流程 一次完整的HTTP请求过程从TCP三次握手建立连接成功后开始,客户端按照指定的格式开始向服务端发送HTTP请求,服务端接收请求后,解析HTTP请求,处理完业务逻辑,最后返回一个HT ...

  8. Python爬虫之编写一个可复用的下载模块

    看用python写网络爬虫第一课之编写可复用的下载模块的视频,发现和<用Python写网络爬虫>一书很像,写了点笔记: #-*-coding:utf-8-*- import urllib2 ...

  9. Python - 装饰器使用过程中的误区

    曾灵敏 - APRIL 27, 2015 装饰器基本概念 大家都知道装饰器是一个很著名的设计模式,经常被用于AOP(面向切面编程)的场景,较为经典的有插入日志,性能测试,事务处理,Web权限校验, C ...

随机推荐

  1. jquery ui tab标签

    <!DOCTYPE html> <html> <head> <title>tab</title> <style type=" ...

  2. centOS7 修改hostname

    hostnamectl set-hostname 你要修改到的hostname   localectl set-locale LANG=要修改的语言     介绍个Centos 7很不错的教程网站:h ...

  3. 【题解】【BST】【Leetcode】Validate Binary Search Tree

    Given a binary tree, determine if it is a valid binary search tree (BST). Assume a BST is defined as ...

  4. Think Python - Chapter 16 - Classes and functions

    16.1 TimeAs another example of a user-defined type, we’ll define a class called Time that records th ...

  5. error: failed to initialize alpm library

    这个问题出在archlinux上面 [root@sarch pacman]# pacman -Syuerror: failed to initialize alpm library(database ...

  6. LCS (nlogn)

    最长上升子序列的O(n*logn)算法分析如下: 先回顾经典的O(n^2)的动态规划算法,设a[t]表示序列中的第t个数,dp[t]表示从1到t这一段中以t结尾的最长上升子序列的长度,初始时设dp [ ...

  7. iOS学习笔记---C语言第三天

    循环结构 : while循环   do...while循环(几乎不用)     for循环(使用最多) 特点:在给定的条件成立时,反复执行某程序段,直到条件不成立为止. 给定的条件为循环条件,反复执行 ...

  8. TCP三次握手连接与四次握手断开

    http://blog.csdn.net/whuslei/article/details/6667471(三次握手与四次握手) 1. TCP的三次握手最主要是防止已过期的连接再次传到被连接的主机. 如 ...

  9. 一张图让你学会LVM

    导读 随着科技的进步,人们不知不觉的就进入了大数据的时代,数据的不断增加我们发现我们的磁盘越来越不够用了,接下来就是令人头疼的事情--加硬盘,数据的备份与还原.LVM就是Linux下专门针对我们数据的 ...

  10. poj 1260 dp

    Description In Pearlania everybody is fond of pearls. One company, called The Royal Pearl, produces ...