首页 > 学院 > 开发设计 > 正文

一只爬虫太慢,那就来一群吧

2019-11-08 19:50:32
字体:
来源:转载
供稿:网友

一只爬虫太慢,那就来一群吧

标签: python 爬虫


多线程爬虫

#导入模块import urllib.request as req import re import time import sqlite3 as sql import threading from queue import Queue #定义全局变量,对爬到的数据计数count = 0 #创建一个自定义类,继承Thread类class GetThred(threading.Thread): #类初始化 def __init__(self, queue, url, pattern): threading.Thread.__init__(self) self.queue = queue self.url = url self.pattern = pattern #重写Tread类的run方法,取出队列中的url def run(self): while True: if not self.queue.empty(): lists = self.queue.get() work(self.url, lists, self.pattern) #做爬虫该做的工作 self.queue.task_done() else: break#定义爬虫如何工作def work(url, lists, pattern): global count con = sql.connect('filename.db') #连接数据库 cur = con.cursor() #获得游标 try: html_i = getHtml(url + lists[0]) #爬取网站内容 lists_every = getLists(html_i, pattern) #解析网页,获得需要的信息 author = lists[1] for i in lists_every[0:3]: dates = i[2].split(' ')[0] times = i[2].split(" ")[1] if dates == time.strftime('%Y-%m-%d'): #丢弃过期数据,当天数据入库 cur.execute('INSERT INTO blogdata VALUES (?,?,?,?,?)', (url + i[0], i[1], dates, times, author)) PRint(lists[1] + ':' + i[1] + ' 获取成功!') count += 1 except Exception as e: print("出现错误:/n",e) finally: cur.close() #关闭游标 con.commit() #提交 con.close() #关闭数据库连接#定义如何爬取网页def getHtml(url): header = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; WOW64; rv:14.0) Gecko/20100101 Firefox/14.0.1', 'Referer': '******'} req.addinfourl(fp=None, headers=header, url=url) request = req.urlopen(url) text = request.read().decode('utf-8') time.sleep(0.01) return text#定义解析网页,提取信息,关键是合理使用正则表达式def getLists(html, pattern): lists = re.findall(pattern, html) return lists#主程序def main(): url = "http://blog.example.com/" #没错,哥爬的是一个博客网站 pattern = re.compile(r'<li><a href=".*?/([^"].*?)">(.*?)</a></li>', re.S) pattern2 = re.compile(r'<span class="title"><a href=".*?/(.*?)" .*?>(.*?)</a>.*?>/((.*?)/)</span>',re.S) html = getHtml(url + 'hotbloger.html') lists = getLists(html, pattern) queue = Queue() #实例化一个队列 for q in lists: #将url加入队列 queue.put(q) for i in range(20): #一狠心放出了20条爬虫 d = GetThred(queue, url, pattern2) d.setDaemon(True) d.start() queue.join()if __name__ == "__main__": start = time.time() #计时开始 main() end = time.time() m, s = divmod(end - start, 60) #百度到转换时间的方法,毫不犹豫借用了 h, m = divmod(m, 60) print('本次爬虫共爬取到', count, '条记录') print('任务完成,共耗时%02d小时%02d分%02d秒' % (h, m, s))
小结:实测某博客网站,作者8000人左右,只爬每位作者最新3篇文章的标题和发表时间,共2万多条信息,对比日期后每次写入数据库500条左右。单线程工作时,全部爬完一遍,需要50分钟到1小时;多线程工作时,一般在3—4分钟收工。尽管因为GIL机制,发挥不了多核CPU的优势,但对于爬虫这种主要耗时在网络请求(IO密集型)的任务,多线程效率明显高得多。另:QQ空间的排版真是个坑,说好的严格缩进呢......
发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表