今天再去爬取另外一个网站 http://pic.netbian.com/
先来看看这个网站的几张图片,我们试图单独爬取看看。


我们单独爬取一下试一试

本地查看,证明图片是可以爬取成功的。
代码如下:

import requests   #导入模块def run4():headers = {'referer': 'http://pic.netbian.com/','user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64; rv:47.0) Gecko/20100101 Firefox/47.0'}with open("D:/estimages/ali.jpg", "wb") as f :f.write(requests.get("http://pic.netbian.com/uploads/allimg/201207/233228-16073551488aeb.jpg", headers=headers).content)f.closewith open("D:/estimages/ali1.jpg", "wb") as f :f.write(requests.get("http://pic.netbian.com/uploads/allimg/200618/005100-1592412660d6f4.jpg", headers=headers).content)f.closewith open("D:/estimages/ali2.jpg", "wb") as f :f.write(requests.get("http://pic.netbian.com/uploads/allimg/190518/174718-1558172838db13.jpg", headers=headers).content)f.closeif __name__ == "__main__":   #主程序入口run4()    #调用上面的run方法

开始开始。。。
接下来我们得分析下这个网站的结构,http://pic.netbian.com/ 是根url,存在多个标签,也是个分层的展示结构。

而且是固定这些标签,数量是固定的,因此我们还是先爬取标签按种类。
随意选首页即可把所有的标签都爬取下来。
而且标签的 href 值是下一层的地址,text文本是标签的文本内容。

点击一个标签进去,发现是一大堆属于该标签的图片,还有分页。
比如我点击的是【4K美女】,地址栏显示的是http://pic.netbian.com/4kmeinv/
此时每张图片的HTML位置如下:在class=”slist”的div块中。

因此我们需要把这个div下所有img都需要爬取出来。

另外分页栏如下:

经过观察可见每个分页栏的命名也是很有规律的啊,因此我们可以推测出 http://pic.netbian.com/4kmeinv/ 是等于http://pic.netbian.com/4kmeinv/index.html ,在浏览器中这样输入,果然是对的,其他的页面都是按照 index_+数字编号的方式。

后面我会把完整代码贴上,需要把save_all_images函数的调用注释掉,且让线程顺序执行的展示结果(也就是在t.start() 后面增加了t.Join(),这样就能顺序执行了),我做了额外处理,就是页面实在太多了,越是做了截断(每个标签最多爬取10个页面)。

这里我还是选择找【下一页】的href值来选择下一个页面。

它处在class=”page”的div中,找到这个【下一页】,得到其href值,就得到了下一个页面的地址。

这样一来,我们的策略就是:
1:先得到所有的标签
2:根据标签建立一个线程单独处理该标签下所有图片
3:每一个标签下,按照分页,一旦访问一个页面,就爬取该页面所有图片。

具体代码如下:

#-*- coding:utf-8 -*-
import os
import requests
from bs4 import BeautifulSoup
import threading
import timerootrurl = 'http://pic.netbian.com/'
save_dir = 'D:/estimages/'
no_more_pages = 'END'
max_pages = 8image_cache = set()
index = len(image_cache)# step 1: 得到所有标签tags
html = BeautifulSoup(requests.get(rootrurl).text.encode('iso-8859-1').decode('gbk'), features="html.parser")
tag_list = {}
for link in html.find('div', {'class': 'classify clearfix'}).find_all('a'):tag_list[link.string] = link.get('href')print("the number of unique tag is : %d" % len(tag_list))
print(tag_list)# step 2: 根据每个标签分别爬取,每个标签点进去都是一个分页
# 因此需要做好分页,鉴于图片太多了,我们需要做个多线程来操作class myThread (threading.Thread):   #继承父类threading.Threaddef __init__(self, threadID, key ,value):threading.Thread.__init__(self)self.threadID = threadIDself.key = keyself.value = valuedef run(self):                   #把要执行的代码写到run函数里面 线程在创建后会直接运行run函数time.sleep(1)print("Thread %d is running..." % self.threadID)self.serachSubPages(self.key, self.value)print("Thread %d is over..." % self.threadID)def serachSubPages(self, key ,value):# 建立这个标签的子目录,图片太多了,按照标签建立子目录,方便存储和整理tag_name = keyif not os.path.exists(save_dir + tag_name):os.mkdir(save_dir + tag_name)print("current tag is : " + tag_name)url = rootrurl + value + 'index.html'pages = 0;while 1:print("next page: " + url)html = BeautifulSoup(requests.get(url).text.encode('iso-8859-1').decode('gbk'), features="html.parser")self.save_all_images(html, save_dir + tag_name)if pages >= max_pages:  #每个标签最多搜索的页面数break;pages = pages + 1url = self.findNextPage(html)if url == no_more_pages:breakurl = rootrurl + urldef save_all_images(self, html, saveDir):global indeximgs = html.find('div', {'class': 'slist'}).find_all('img')print('total imgs is %d:' % len(imgs))for img in imgs:# 有一些图片的href是src, 有一些图片的href是original,因此都是要考虑的。href = img.get('src')print(href)# 判断是否重复下载if href not in image_cache:with open('{}/{}'.format(saveDir, href.split("/")[-1]), 'wb') as jpg:  # 请求图片并写进去到本地文件jpg.write(requests.get(rootrurl + href).content)image_cache.add(href)print("正在抓取第%s条数据" % index)index += 1def findNextPage(self, html):nextBtn = html.find('div', {'class': 'page'}).find_all('a')  # 找到next按钮,获得下一个连接网页的位置for link in nextBtn:if link.string == '下一页':return link.get('href')[1:]return no_more_pagesif __name__ == '__main__':i = 0thread_list = []for key ,value in tag_list.items():thread1 = myThread(i, key ,value[1:])  # 创建多个线程去分别爬取各个标签页的数据thread_list.append(thread1)i=i+1for t in thread_list:# t.setDaemon(True)  # 设置为守护线程,不会因主线程结束而中断t.start()

效果如下:


Python《多线程并发爬虫》相关推荐

  1. Github配置(git+vscode+python+jupyter)

    ①下载git 打开 git bash 工具的用户名和密码存储 $ git config --global user.name "Your Name" $ git config -- ...

  2. 【实验楼】python简明教程

    ①终端输入python进入 欣赏完自己的杰作后,按 Ctrl + D 输入一个 EOF 字符来退出解释器,你也可以键入 exit() 来退出解释器. ②vim键盘快捷功能分布 ③这里需要注意如果程序中 ...

  3. 【Kaggle Learn】Python 5-8

    五. Booleans and Conditionals Using booleans for branching logic x = True print(x) print(type(x))''' ...

  4. 【Kaggle Learn】Python 1-4

    [Kaggle Learn]Python https://www.kaggle.com/learn/python 一. Hello, Python A quick introduction to Py ...

  5. 使用python愉快地做高数线代题目~

    今天接触到了python,发现真是极易上手啊!对比c语言是什么鬼东西= = 诶,等下,看完教学文章发现TA在下面写了这句话 如果做了前面的内容你可能已被吸引了,觉得c语言真的是废材! 不...不是的. ...

  6. python 位运算与等号_Python 运算符

    和大多数语言一样,Python也有很多运算符,并且运算符跟其他语言的运算符大同小异接下来一一介绍: 算术运算符: 运算符描述实例 +加 - 两个对象相加a+b的输出结果是30 -减 - 得到复数或者一 ...

  7. python减小内存占用_如何将Python内存占用缩小20倍?

    当程序执行过程中RAM中有大量对象处于活动状态时,可能会出现内存问题,特别是在对可用内存总量有限制的情况下. 下面概述了一些减小对象大小的方法,这些方法可以显著减少纯Python程序所需的RAM数量. ...

  8. python中排序英文单词怎么写_Python实现对文件进行单词划分并去重排序操作示例...

    本文实例讲述了Python实现对文件进行单词划分并去重排序操作.,具体如下: 文件名:test1.txt 文件内容: But soft what light through yonder window ...

  9. python程序如何执行死刑图片_如何判断对象已死

    已死的对象就是不可能被任何途径使用的对象,有以下几种方法判断一个对象是否已经死了: 引用计数 给对象添加一个引用计数器,每当有一个地方引用他,计算器就加 1:当引用失效时,计数器减 1:任何时刻计数器 ...

  10. Python gRPC 安装

    1. 安装依赖库 sudo pip3 install grpcio sudo pip3 install protobuf sudo pip3 install grpcio_tools 2. 生成对应文 ...

最新文章

  1. AI 技术发展飞快,高校 AI 教师的知识储备能满足学生旺盛的求知欲吗?
  2. Java Swing 皮肤
  3. linux shell dig nslookup 指定dns服务器 查询域名解析
  4. 一种巧妙的删除程序自己的方法
  5. 2021年下半年系统集成项目管理工程师案例分析真题及答案解析
  6. idea中.ignore插件的使用
  7. C++内存泄漏的几种情况
  8. 怎样理解“道不同,不相为谋”这句话呢。。。
  9. spring boot 源码_springboot源码架构解析listener
  10. 想自学python看哪位的视频比较好-python自学视频看这个就对了
  11. python题目关于企业利润_Python练习题(一)
  12. 如何使用monitor(DDMS)抓取traceview文件
  13. c语言开发unity,[Unity3D]U3D开发项目总结
  14. CVPR2021 最具创造力的那些工作成果!或许这就是计算机视觉的魅力!
  15. C语言递归解决水洼问题
  16. 中断系统与定时/计数计时器
  17. 潜力无限的BTF,开启区块链金融新格局
  18. 爬虫实战1:爬取糗事百科段子
  19. C语言旅途之用switch计算本利和
  20. matlab求椭圆的弧长,用MATLAB实现求椭球上任意两点的最短弧长

热门文章

  1. 一起Polyfill系列:让Date识别ISO 8601日期时间格式
  2. 使用SafeViewFlipper避免ViewFlipper交替时Crash
  3. 《大话设计模式》读书笔记-第13章 建造者模式
  4. 图片服务 - thumbor详细介绍
  5. Windows10 部署 Sonarqube 代码质量管理平台
  6. 创建设计模式 - 抽象工厂设计模式
  7. Top20的OpenSSH服务器最佳安全实践--SSHD_CONFIG配置文件详细解读
  8. jQuery 源码解析(三十一) 动画模块 便捷动画详解
  9. C语言 找出任意两整数之间的素数以及他们的和
  10. 【JAVA 第三章 流程控制语句】课后习题 判断用户输入的数是否为质数