赞
踩
爬虫课题描述可见:
课题解决方法:
微博移动版爬虫
微博PC网页版爬虫
Python爬虫【二】爬取PC网页版“微博辟谣”账号内容(selenium同步单线程)
Python爬虫【三】爬取PC网页版“微博辟谣”账号内容(selenium单页面内多线程爬取内容)
Python爬虫【四】爬取PC网页版“微博辟谣”账号内容(selenium多线程异步处理多页面)
前面专题文章【二】中,我们编写了微博PC网页版单线程的爬虫方式。但执行速度较慢,需要约两个小时才能处理完成。
此文我们对之前的程序略作改造,让其实现在每个页面内爬取45条数据时,进行多线程异步爬取,从而缩短每个页面的爬取时间,进而缩短整个爬取时间。
对于整个设计流程,之前CrawlHandle
串行方法内的逻辑没有问题,仍然是执行五个步骤。前面的启动driver、登录认证,后面的关闭driver、写入数据,都没有变化。
唯一需要变化的是步骤三,此时Crawl类在爬取时,应该去选择是执行多线程还是单线程。因为是改造,所以我们用一个开关来控制Crawler是走单线程还是多线程,构造函数增加一个入参。
class Crawler:
"""
爬取类,负责下拉、翻页、爬取,将最终结果存入df
"""
def __init__(self, async_crawler_in_page=True):
"""
初始化处理类所需必要的属性
"""
self.async_crawler_in_page = async_crawler_in_page
# 定义空df,以装载处理完的数据
self.excel_df = DataFrame(columns=EXCEL_COLUMNS)
# 声明driver
self.driver = None
可以看到传入了一个新入参async_crawler_in_page
,为true时走并发爬取,否则还是之前的串行爬取
在def __crawler_page_and_save_df()
方法中,进行参数判断。改造如下:
def __crawler_page_and_save_df(self): """ 使用selenium工具爬取当前微博页面信息 :param page: :param driver: :return: """ wb_page_start_time = time.time() # 用于计时 wb_list = [] # print("开始爬取第 %i 页数据..." % self.page) try: # 1. 找出微博内容框架list,也就是每个微博内容块的集合 # wb_cardwrap_list = driver.find_elements_by_xpath("//div[@action-type='feed_list_item']") #尽量不用xpath,提高效率 wb_cardwrap_list = self.driver.find_elements_by_class_name("WB_feed_type") # XXX 改造点:进行判断 if self.async_crawler_in_page: # 多线程处理,每个线程解析一个微博内容框架,从中提取所需数据 wb_list = self.__async_crawler_weibo_info(wb_cardwrap_list) else: # 单线程处理, 爬取框架list中的微博数据,返回wb_list wb_list = self.__sync_crawler_weibo_info(wb_cardwrap_list) except: print("爬取处理 第 %i 页html数据时出错! ", self.page) traceback.print_exc() else: print("成功爬取第 %i 页数据,爬取有效微博数:%s, 处理本页数据耗时:%s " % (self.page, len(wb_list), time.time() - wb_page_start_time)) # 不为空则写入df中 if wb_list: self.excel_df = self.excel_df.append(wb_list)
上面调用了异步并行处理新写的方法:def __async_crawler_weibo_info()
def __async_crawler_weibo_info(self, wb_cardwrap_list): """ 用多线程方式异步并发爬取微博内容 :param wb_cardwrap_list: :return: """ wb_list = [] # 爬取到的微博信息整理后的储存list thread_list = [] for wb_count in range(len(wb_cardwrap_list)): # 多线程:约18秒左右处理完45条数据,比单线程串行30~36秒左右减少一半时间。 Python多线程是伪多线程 thread = util.WBCrawlerThread(util.crawler_weibo_info_func, (wb_cardwrap_list[wb_count], self.page, wb_count)) thread_list.append(thread) thread.start() # 取结果 for thread in thread_list: thread.join() # 去除None,将结果存入list中 if thread.result: wb_list.append(thread.result) return wb_list
这里用到了python的并行处理逻辑,自定义多线程工具类WBCrawlerThread
,继承python自有类Thread,如下:
class WBCrawlerThread(threading.Thread): """ 多线程工具类 """ def __init__(self, func, args=()): super(WBCrawlerThread, self).__init__() self.func = func self.args = args def run(self): self.result = self.func(*self.args) def get_result(self): try: return self.result except Exception: return None
可见:
def crawler_weibo_info_func()
函数(参见前一篇博文);后面的参数即为此函数执行时所需要传入的参数。def __async_crawler_weibo_info()
方法内,程序为每个wb_cardwrap_list内的对象创建一个WBCrawlerThread对象进行异步爬取,因此总共启动约45个多线程执行爬取操作wb_list
返回,与之前串行的数据格式和大小都一致if __name__ == '__main__':
# 网页版微博爬取,使用多线程
crawler = line_crawl.Crawler(async_crawler_in_page=True)
crawl_handle.crawl_wb_and_write_excel(crawler)
以上即为selenium单页面内多线程爬取内容的改造
执行过程中,前面登录与单线程没区别;但当用户登录成功,下拉两次后,开始爬取时:可以看到后台不再是按微博上下顺序依次爬取、每条微博处理完成后打印日志的间隔时间也不再标准,而是有快有慢,符合并行处理的情况
因为本地计算机性能有限,电脑CPU核心固定(一般都是2核到8核),因此实际上不可能45个多线程完全并发执行。并且有人分析python的Thread实现逻辑,发现其并非为真正的多线程,而是伪多线程并非真正做到多核高并发。因此最后爬取的结果来看,仍是存在先后排队 ,大多等待、少数执行的情况;但整体上多线程还是使用了更多的CPU资源,会提高整体的爬取效率。
博主笔记本为酷睿i5二核,经测算每个页面的爬取效率可以提升一倍,原先一个页面串行爬取需要30s~36s,改造多线程后;用时约18s;结合下拉翻页,整个项目爬取时间缩短为1.7个小时
项目工程编译了windows版本执行程序:微博数据采集python+selenium执行程序:WBCrawler.exe
执行项目前,需要下载selenium对应的浏览器驱动程序(driver.exe),并放在本机环境变量路径中,否则会报错。安装操作具体可见博客专题中的指导【二】
执行程序时,会在系统用户默认路径下,创建一个虚拟的python环境(我的路径是C:\Users\Albert\AppData\Local\Temp_MEI124882\),因此启动项目所需时间较长(约20秒后屏幕才有反应,打出提示),请耐心等待;也正因如此,执行电脑本身环境是可以无需安装python和selenium依赖包的;同时最后爬取保存的excel也在此文件夹下。
本项目采用cmd交互方式执行,因此等到屏幕显示:
选择爬取方式:
1. 移动版微博爬取
2. PC网页版微博爬取(单线程)
3. PC网页版微博爬取(页面内多线程)
4. PC网页版微博爬取(多线程异步处理多页面)
后,用键盘输入1~4,敲回车执行
工程参见:微博数据采集python+selenium工程:WBCrawler.zip
本专题内对源码粘贴和分析已经比较全面和清楚了,可以满足读者基本的学习要求。源码资源为抛砖引玉,也只是多了配置文件和一些工具方法而已,仅为赶时间速成的同学提供完整的项目案例。大家按需选择
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。