:点击上方[Python爬虫数据分析挖掘]→右上角[...]→[设为星标⭐]

多线程爬取表情包

有一个网站,叫做“斗图啦”,网址是:https://www.doutula.com/。这里面包含了许许多多的有意思的斗图图片,还蛮好玩的。有时候为了斗图要跑到这个上面来找表情,实在有点费劲。于是就产生了一个邪恶的想法,可以写个爬虫,把所有的表情都给爬下来。这个网站对于爬虫来讲算是比较友好了,他不会限制你的headers,不会限制你的访问频率(当然,作为一个有素质的爬虫工程师,爬完赶紧撤,不要把人家服务器搞垮了),不会限制你的IP地址,因此技术难度不算太高。但是有一个问题,因为这里要爬的是图片,而不是文本信息,所以采用传统的爬虫是可以完成我们的需求,但是因为是下载图片所以速度比较慢,可能要爬一两个小时都说不准。因此这里我们准备采用多线程爬虫,一下可以把爬虫的效率提高好几倍。

文章目录

1、爬取准备

2、完整代码

3、图片辅助分析

4、运行结果

1、爬取准备

爬取目标

https://www.doutula.com/article/list/

批量爬取

温馨提示:爬取过程中保持网络通畅,不然会爬取失败!

这里多线程我们使用的是Python自带的threading模块。并且我们使用了一种叫做生产者和消费者的模式,生产者专门用来从每个页面中获取表情的下载链接存储到一个全局列表中。而消费者专门从这个全局列表中提取表情链接进行下载。并且需要注意的是,在多线程中使用全局变量要用锁来保证数据的一致性。

ps:感兴趣的小伙伴可以试试线程池

使用线程池

线程池或进程池是用于在程序中优化和简化线程/进程的使用。通过池,你可以提交任务给executor。池由两部分组成,一部分是内部的队列,存放着待执行的任务;另一部分是一系列的进程或线程,用于执行这些任务。池的概念主要目的是为了重用:让线程或进程在生命周期内可以多次使用。它减少了创建创建线程和进程的开销,提高了程序性能。重用不是必须的规则,但它是程序员在应用中使用池的主要原因。

2、完整代码

import requestsfrom threading import Threadfrom queue import Queuefrom lxml import etreeimport timeimport osimport random# 请求头headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.193 Safari/537.36"}path = "./图片"#数据采集class CrawlInfo(Thread):def __init__(self ,url_queue ,html_queue):Thread.__init__(self)self.url_queue = url_queueself.html_queue = html_queuedef run(self):# 不存在就创建if not os.path.exists(path):# mkdir是创建文件夹os.mkdir(path)while self.url_queue.empty() == False:url = self.url_queue.get()response = requests.get(url,headers=headers)#请求成功状态码为200则进行putif response.status_code == 200:self.html_queue.put(response.text)# 数据解析、保存class ParseCrawl(Thread):def __init__(self, html_queue):Thread.__init__(self)self.html_queue = html_queuedef run(self):#队列不为空则继续遍历while self.html_queue.empty() == False:data = etree.HTML(self.html_queue.get())#查看图1,根据class定位获取其下的所有a标签a_list = data.xpath("//div[@class='col-sm-9 center-wrap']/a")#遍历a标签for a_singer in a_list:#查看图2,重新写xpath根据class定位#text():获取文本值name = a_singer.xpath(".//div[@class='random_title']/text()")[0]#替换掉name中的\u200b\u200b\u200b字符串name = str(name).replace("\u200b\u200b\u200b","")#拼接新的路径new_path = path + "/" + name#新路径不存在就创建if not os.path.exists(new_path):os.mkdir(new_path)#获取图片url,查看图3#根据class值定位到所有img的父标签,在根据img的class拿到所有img的data-original属性即图片url,这里不拿src属性是因为爬取时拿到的是图片还未加载完毕的urlimg_url_list = a_singer.xpath(".//div[@class='random_article']//img[@class='lazy image_dtb img-responsive']/@data-original")#遍历img_url_listfor img in img_url_list:#由于图片有jpg、png、gif格式,这里我们根据'.'分割获取图片格式后缀suffix = "." + str(img).split(".")[-1]#发起请求,content为二进制re = requests.get(img,headers=headers).content#图片命名为随机数str(random.randint(1,500))with open(new_path + "/" + str(random.randint(1,500)) + str(suffix), "wb") as f:#保存图片f.write(re)#开始if __name__ == '__main__':start = time.time()url_queue = Queue()html_queue = Queue()base_url = "https://www.doutula.com/article/list/?page={}"#我们这只爬取13页for i in range(1,14):print("正在爬取第{}页".format(i))new_url = base_url.format(i)url_queue.put(new_url)crawl_list = []for i in range(3):Crawl = CrawlInfo(url_queue, html_queue)crawl_list.append(Crawl)Crawl.start()for crawl in crawl_list:crawl.join()parse_list = []for i in range(3):parse = ParseCrawl(html_queue)parse_list.append(parse)parse.start()for parse in parse_list:parse.join()end = time.time()print("爬取时间:{}".format(end- start))

以上这份代码。可以完整的运行了。采用多线程,在一张图片下载的时候,就完全可以去请求其他图片,而不用继续等待了。因此效率比较高。

3、图片辅助分析

图1

图2

图3

4、运行结果

写在最后:

本教程采用多线程来完成表情的爬取,可以让爬取效率高出很多倍。Python的多线程虽然有GIL全局解释器锁,但在网络IO处理这一块表现还是很好的,不用在一个地方一直等待。以上这个例子就很好的说明了多线程的好处。

【各种爬虫源码获取方式】

识别文末二维码,回复:爬虫源码

- END -

欢迎关注公众号:Python爬虫数据分析挖掘,方便及时阅读最新文章

记录学习python的点点滴滴;

回复【开源源码】免费获取更多开源项目源码;

最新文章

  1. XML篇---可配置化的取值方式[便于维护]
  2. 为什么需要握三次手,两次或者四次可以吗??
  3. 两个大文件找出相同的一条记录
  4. json字符串转换成json对象
  5. [转载] Python列表操作
  6. 苏州为什么只能做二线中游?
  7. css光盘转动,CSS 实现加载动画之五-光盘旋转
  8. vc 获得桌面文件坐标_为何 Elementary OS 中使用 Pantheon 桌面
  9. 随机森林模型调参方法
  10. Excel在行上面一键定位可见单元格!
  11. Oracle中文乱码(中文变问号?)解决方法---简单粗暴高效
  12. GNU 软件文档下载
  13. java 操作word宏_java调用microsoft office(如word、excel)的宏 | 学步园
  14. 零基础自学Python好难?学起来很吃力,想放弃?看看别人是怎样学习的
  15. 如何使用自己的云服务器做代理服务器
  16. 什么软件可以查手机卡的imsi_手机SIM卡卡号和IMSI码怎么查询
  17. C++课程设计-失物招领系统
  18. 物联网大白话之一-什么是物联网
  19. 分布式系统以及分布式系统架构的优缺点
  20. React使用axios的坑:每次都要请求两次,而且前后端相同配置,有的url可以,有的确不可以

热门文章

  1. 在表中插入数据的SQL语句
  2. 给最近正在找工作(iOS)的朋友一些建议/经验
  3. 设置打开Finder的快捷键
  4. 移动办公oa系统该如何搭配其他工具使用?
  5. 怀旧电影 -- 《郝邵文\释小龙影集》
  6. 【吃灰板子捡起来】新字符设备驱动开发实验
  7. 献礼20周年! 互联网研发管理现状主题分享
  8. 英语单词学习-17-112
  9. Azure Key Vault入门
  10. 给简书找BUG赢好礼17.06.02——简书Android 2.4.0 公测【私密文章支持预览/手机支持直接提现】...