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

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

前言

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

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

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

成果演示

先来看看最后的成果:

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

确认需求

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

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

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

每个主题的详细图片:

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

html 节点分析

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

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

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

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

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

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

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

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

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

3. 思维导图爬取思路

代码设计思路

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

部分代码讲解

来简单的看部分代码:


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 上了。

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

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

已标记关键词 清除标记
©️2020 CSDN 皮肤主题: 创作都市 设计师:CSDN官方博客 返回首页