手把手教你用Python网络爬虫进行多线程采集高清游戏壁纸

一、背景介绍

大家好,我是皮皮。对于不同的数据我们使用的抓取方式不一样,图片,视频,音频,文本,都有所不同,由于网站图片素材过多,所以今天我们使用多线程的方式采集某站4K高清壁纸。

二、页面分析

目标网站:

http://www.bizhi88.com/3840x2160/

如图所示,有278个页面,这里我们爬取前100页的壁纸图片,保存到本地;

解析页面

如图所示所哟鱼的图片在一个大盒子里面(<div class="flex-img auto mt"></div>),下面每一个div就对应一张高清壁纸;

然后每页div标签里面的壁纸图片数据的各种信息:1.链接;2.名称;下面是xpath的解析;

1imgLink = each.xpath("./a[1]/img/@data-original")[0] 2name = each.xpath("./a[1]/img/@alt")[0]

有一个注意点:

图片标签有src属性也有data-original属性,都对应图片的url地址,我们一般使用后者,因为data-original-src是自定义属性,图片的实际地址,而src属性需要页面加载完全才会全部显现,不然得不到对应地址;

三、抓取思路

上面已经说过,图片数据过多,我们不可能写个for循环一个一个的下载,所以必然要使用多线程或者是多进程,然后把这么多的数据队列丢给线程池或者进程池去处理;在python中,multiprocessing Pool进程池,multiprocessing.dummy非常好用,

  • multiprocessing.dummy 模块:dummy 模块是多线程;
  • multiprocessing 模块:multiprocessing 是多进程;

multiprocessing.dummy 模块与 multiprocessing 模块两者的api 都是通用的;代码的切换使用上比较灵活;

页面url规律:

1'http://www.bizhi88.com/s/470/1.html' # 第一页 2'http://www.bizhi88.com/s/470/2.html' # 第二页 3'http://www.bizhi88.com/s/470/3.html' # 第三页

构建的url:

page = 'http://www.bizhi88.com/s/470/{}.html'.format(i)

那么我们定制两个函数一个用于爬取并且解析页面(spider),一个用于下载数据 (download),开启线程池,使用for循环构建13页的url,储存在列表中,作为url队列,使用**pool.map()**方法进行spider,爬虫的操作;

1 def map(self, fn, *iterables, timeout=None, chunksize=1): 2 """Returns an iterator equivalent to map(fn, iter)”“” 3 这里我们的使用是:pool.map(spider,page) # spider:爬虫函数;page:url队列

作用:将列表中的每个元素提取出来当作函数的参数,创建一个个进程,放进进程池中;

参数1:要执行的函数;

参数2:迭代器,将迭代器中的数字作为参数依次传入函数中;

四、数据采集

导入相关第三方库

1from lxml import etree # 解析 2import requests # 请求 3from multiprocessing.dummy import Pool as ThreadPool # 并发 4import time # 效率

页面数据解析

1def spider(url): 2 html = requests.get(url, headers=headers) 3 selector = etree.HTML(html.text) 4 contents = selector.xpath("//div[@class='flex-img auto mt']/div") 5 item = {} 6 for each in contents: 7 imgLink = each.xpath("./a[1]/img/@data-original")[0] 8 name = each.xpath("./a[1]/img/@alt")[0] 9 10 item['Link'] = imgLink 11 item['name'] = name 12 towrite(item)

download下载图片

1def download_pic(contdict): 2 name = contdict['name'] 3 link = contdict['Link'] 4 with open('img/' + name + '.jpg','wb') as f: 5 data = requests.get(link) 6 cont = data.content 7 f.write(cont) 8 print('图片' + name + '下载成功!')

main() 主函数

1 pool = ThreadPool(6) 2 page = [] 3 for i in range(1, 101): 4 newpage = 'http://www.bizhi88.com/s/470/{}.html'.format(i) 5 page.append(newpage) 6 result = pool.map(spider, page) 7 pool.close() 8 pool.join()

说明:

  1. 在主函数里我们首选创建了六个线程池;
  2. 通过for循环动态构建100条url;
  3. 使用map() 函数对线程池中的url进行数据解析存储操作;
  4. 当线程池close的时候并未关闭线程池,只是会把状态改为不可再插入元素的状态;

五、程序运行

1if __name__ == '__main__': 2 start = time.time() # 开始计时 3 main() 4 print(end - start) # 时间差

结果如下:

当然了这里只是截取了部分图像,总共爬取了,2000+张图片。

六、总结

本次我们使用了多线程爬取了某壁纸网站的高清图片,如果使用requests很明显同步请求并且下载数据是比较慢的,所以我们使用多线程的方式去下载图片,提高了爬取效率。

点赞
收藏

评论区

加载中...

相关推荐

MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1

文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s

Oracle 分组与拼接字符串同时使用

SELECTT.,ROWNUMIDFROM(SELECTT.EMPLID,T.NAME,T.BU,T.REALDEPART,T.FORMATDATE,SUM(T.S0)S0,MAX(UPDATETIME)CREATETIME,LISTAGG(TOCHAR(

MySQL部分从库上面因为大量的临时表tmp_table造成慢查询

背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_

皕杰报表之UUID

​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为

2020年前端实用代码段,为你的工作保驾护航

有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )

Python3:sqlalchemy对mysql数据库操作,非sql语句

Python3:sqlalchemy对mysql数据库操作,非sql语句python3authorlizmdatetime2018020110:00:00coding:utf8'''