100行代码教你爬取斗图网(Python多线程队列)

前言

根据之前写的两篇文章,想必大家对多线程和队列有了一个初步的了解,今天这篇文章就来实战一下,用多线程 + 队列 爬取斗图网的全网图片。

你还在为斗图找图片而烦恼吗?快来跟我一起 happy 吧!

PS:本文目的是抱以学习心态而分享,禁止用于非法以及商业途径,如有风险,一切后果自己承担!

成果演示

先来看看最后的成果:

100行代码教你爬取斗图网(Python多线程队列)_python

100行代码教你爬取斗图网(Python多线程队列)_python_02

100行代码教你爬取斗图网(Python多线程队列)_python_03

启动程序后,可以发现目录下是同时出现 5 个主题图片(线程设置了 5 个,所以同时创建 5 个文件夹)的,每个主题文件夹下都有相应的图片。

确认需求

开始之前,先来看下要爬取的网站以及图片,对其进一步进行分析。

  1. 要爬取的网站 - 斗图啦

100行代码教你爬取斗图网(Python多线程队列)_多线程_04

  1. 要爬取的内容,肯定就是图片啦

100行代码教你爬取斗图网(Python多线程队列)_html_05

每个主题的详细图片:

100行代码教你爬取斗图网(Python多线程队列)_多线程_06

100行代码教你爬取斗图网(Python多线程队列)_python_07

从斗图啦主页点到详情页可以看到,每个主题下有好多图片,所以需求就是爬取 1 - 615 页每页中详情页的图片。

html 节点分析

首先,在斗图啦首页列表中一共有 615 页,每次点击不同页时,可以观察到地址的变化:

100行代码教你爬取斗图网(Python多线程队列)_斗图网_08

100行代码教你爬取斗图网(Python多线程队列)_多线程_09

不难发现,点击第几页时,网页地址后面的 page 就是几。

分析好网站的分页后,可以按照正常流程的逻辑进行 HTML 源码的分析,打开 F12 ,让我们来一步步进行梳理。

1. 分析每页的主题 url 地址

比如第一页中,要爬取其下的所有主题,而每个主题下又有具体的详情图片。所以第一步需要分析点击每个主题后的 url 地址。如下图:

100行代码教你爬取斗图网(Python多线程队列)_html_10

100行代码教你爬取斗图网(Python多线程队列)_python_11

这样一来,确定了第一页中,所有主题的具体详情页地址:

100行代码教你爬取斗图网(Python多线程队列)_爬虫_12

2. 分析每个主题下详情页的各个图片地址

用第一个企鹅表情举例,当我们点入到此主题后,F12继续分析每个图片的具体地址:

100行代码教你爬取斗图网(Python多线程队列)_爬虫_13

再次分析,可以发现,所有图片其实结构都一样,只需要提取下图的图片地址即可完成:

100行代码教你爬取斗图网(Python多线程队列)_多线程_14

3. 思维导图爬取思路

100行代码教你爬取斗图网(Python多线程队列)_爬虫_15

代码设计思路

上面分析完,接下来讲下笔者的设计思路,代码不唯一,爬取的思路提供给大家了,也可自行先写一个玩玩看,然后在对比咱们写的代码有什么不同处。。

100行代码教你爬取斗图网(Python多线程队列)_爬虫_16

部分代码讲解

来简单的看部分代码:

def main():
print('程序开始!')

thread_nums = 5 # 开启 5 个线程
for main_url in range(1, 615):
url = f'https://www.doutula.com/article/list/?page={main_url}'
DouTuLaSpider.url_queue.put(url)

doutu = DouTuLaSpider()
# 开启多线程
for i in range(thread_nums):
thread = threading.Thread(target=doutu.run)
thread.start()
thread.join()

print('程序结束...')
def run(self):
""" 通过队列来实现多线程的有序性,从第 1 页到第 614 页有序处理 """
try:
while 1:
url_queue = DouTuLaSpider.url_queue
if url_queue.qsize() == 0:
break
else:
main_url = url_queue.get()
html = self.__crawl_html(main_url)
self.__control_speed() # 加延时
self.__analysis_main_url(html) # 分析主节点
except Exception as e:
import traceback
traceback.print_exc()

入口地方,开启 5 个线程,分别将所有页数的地址放入队列中,然后让线程去队列中有序的获取分页的地址。

如果有细看代码的同学,会发现上面的代码是 1-614 页,因为代码是前天写的,那会儿还只有 614 ,斗图啦网站每日都有更新哟。。

简单的说下为什么要用队列?就是因为有序,多线程下,如果不引用队列的话,有可能会出现爬取重复的url地址呀。。。不理解的话想想这个问题:你怎么知道哪个是你爬取过的的地址呢?

其余的具体提取操作代码就不放了。

当然,我们是为了学习,而不是为了攻击人家服务器。。。爬取的时候该控制速度就要控制速度,在源码中已经对应提供了。而笔者这里作为演示,也没有全爬取,就是爬取了一小部分而已。

总结

如果有想要全部代码的同学,老规矩,公众号后台回复 斗图啦,完整代码已经放到了 github 上了。

关于多线程和队列不理解的同学,欢迎看下之前写的两篇文章。如果有哪里不懂的,欢迎留言区留言交流。期待你的留言呐!

100行代码教你爬取斗图网(Python多线程队列)_爬虫_17

100行代码教你爬取斗图网(Python多线程队列)_多线程_18

欢迎关注:migezatan.(咪哥杂谈)