QQ登录

只需一步,快速开始

扫描二维码登录本站

切换到宽版
微信扫一扫 分享朋友圈

已有 937 人浏览分享

手把手教你爬取漂亮小姐姐!

[复制链接]
发表于 2021-10-10 15:56:58 | 显示全部楼层 | 阅读模式
w1.jpg
更多精彩,请点击上方蓝字关注我们!

w2.jpg

Python简单爬图

w3.jpg

上次分享的阿里云盘170G资料,有不少小伙伴看上了其中的美图,后面可能是分享者移除了,今天就教你们使用Python爬取某图片站的美图,为什么选这个站,主要是因为这个站点的美图都美得很规矩
w4.jpg


w5.jpg

在写代码之前,肯定是要对目标站点进行一些简单分析,从逻辑上把关系理顺,这样后面开始写代码的时候照着分析的逻辑写,就会少很多麻烦。

w6.jpg

整体逻辑大概如上图所示,下面进入正题,视频放在最后。

w7.jpg

网站有搜索功能,所以我们就从搜索开始,打开浏览器开发者工具,切换到网络视图,输入搜索关键词,点击搜索

w8.jpg

可以看到很显眼的search.php,请求类型是post,请求参数如下:
typeid=0q=%C3%C0%C5%AEsubmit=%CB%D1%CB%F7

这是什么鬼?熟悉的小伙伴一眼就能猜到,q、submit参数肯定是url编码,我们看一下

w9.jpg

其实就是对参数进行了gb2312的url编码,通常一般网站都采用utf8格式,但这个站全部是gbk编码,所以后面咱们也需要对搜索关键词进行gbk编码。

三个参数,typeid看字面意思就是类型,应该是对应选择的搜索分类,q参数就是我们的搜索关键词,submit参数经测试是固定不变的,这里我们去看一下这个typeid分类id有哪些,在综合上面点击鼠标右键,选择审查元素

w10.jpg

会自动切换到元素面板,并定位到所选的元素部分代码,如下:

w11.jpg

可以看到,各个分类对应的typeid,也就是上图中的 option value值。

知道了参数,我们再看一下搜索结果,在页面底部可以看到分页按钮:

w12.jpg

它有什么用呢?它的用处就在于我们需要获取到搜索结果的总页数,以方便后续的访问下载,我们在页面点击鼠标右键,选择查看网页源代码,搜索“末页”

w13.jpg

可以看到它是一个很长的链接,图片看不清楚,放到代码里看一下

<ahref='/plus/search.php?keyword=%C3%C0%C5%AE&searchtype=titlekeyword&channeltype=0&orderby=&kwtype=0&pagesize=20&typeid=0&TotalResult=28072&PageNo=15'>末页</a>

这个链接里包含有几个比较重要的参数,如下:
keyword:搜索关键词(经过GBK编码)pagesize:默认20,表示默认每页显示20个图集typeid:搜索分类TotalResult:搜索结果图集总数量PageNo:当前页码

知道了上述参数后,我们就可以按照格式自行构造一个url请求,直接一步获取所有图集,不需要再一页一页的采集,怎么做?很简单,将上述参数中的pagesize默认的20直接修改为TotalResult值,应该不难理解,就是将默认每页显示20个图集改成了一页显示所有图集,然后PageNo这个参数可以直接去掉不要,测试构造url如下:

/plus/search.php?keyword=%C3%C0%C5%AE&searchtype=titlekeyword&channeltype=0&orderby=&kwtype=0&pagesize=28072&typeid=0&TotalResult=28072

模拟发送测试,结果完全符合我们的猜测,一次就获取到了28072个图集,请注意,因为图集数量太大,浏览器需要很长时间才可以显示完成。

到这一步,我们已经可以获取到搜索的所有图集,下一步是干嘛,当然是解析每个图集的url地址

同样,鼠标右键选择查看网页源代码:

w14.jpg

可以看到,标注红色部分就是我们需要获取的每个图集的url地址,标注绿色部分则是图集的名称,当然,你们也可以使用xpath等方式进行获取,我个人习惯使用万能的re正则表达式获取,正则表达式如下:

<ahref="(.*?)"target="_blank"title="(.*?)">
注意,因为有多个结果,所以需要使用 re.findall

获取到每个图集的url地址和图集名称以后,最后当然就是访问每个图集,下载图片了,这部分就当留给小伙伴们的作业,不会的地方可以参照下面的完整代码。

完整代码如下(python 3.x):

(因为只是简单演示,所以并没有使用多线程,有需要的小伙伴自己改改)
# -*- coding: utf-8 -*-# @Author: Null119# @Desc: { 某站图片下载 }# @Date: 2021/08/14 16:36
import urllib,requests,re,os,time
weburl='http://www.jj20.com'
headers={"Content-Type":"application/x-www-form-urlencoded",}
defsearch(stype,words,pageCount):'''    :param stype: 搜索类型,0:综合,243:壁纸,244:明星,131:图片,130:头像    :param words: 搜索关键词    :param pageCount: 指定下载图集数量    :return:    '''    postdata={'typeid':stype,'q':words,'submit':'搜索'    }#对表单进行gbk编码,再进行urlencode    data_gb2312 = urllib.parse.urlencode(postdata, encoding='gb2312')#post搜索请求    htm=requests.post(weburl+'/plus/search.php',data=data_gb2312,headers=headers).text#正则匹配搜索结果图集总数    total=re.search(r'TotalResult=(\d+)',htm).group(1)if int(total)<pageCount:        pageCount=int(total)#构造Url实现一次请求获取所有图集信息    nUrl='%s/plus/search.php?keyword=%s&searchtype=titlekeyword&channeltype=0&orderby=&kwtype=0&pagesize=%d&typeid=%d&TotalResult=%d' % (weburl,urllib.parse.quote(words.encode('gbk')),pageCount,stype,pageCount)    htm=requests.get(nUrl)#正则匹配所有图集url、图集名称    sinfo=re.findall(r'<a href="(.*?)" target="_blank" title="(.*?)">',htm.text)#因为图集名称里包含有很多的<...>的html内容,所以使用正则进行匹配后进行替换去除#而re.findall返回结果是tuple类型,无法进行修改,所以这里创建一个list,用于保存对获取到的图集名称进行处理的结果    slist=[]for i in range(len(sinfo)):        title=sinfo[1]#正则匹配图集标题中的<...>内容        rtest=re.findall('<.*?>',title)for j in rtest:#将匹配到的<...>内容替换为空            title=title.replace(j,'')#将处理好的图集标题,以及拼接好的图集完整url添加到list        slist.append([weburl+sinfo[0],title])    getpiclist(slist,words)
defgetpiclist(slist,words):'''    :param slist: 图集信息list    :param words: 搜索关键词(主要用于最后保存图片时建立对应文件夹)    :return:     '''    picurllist=[]for i in range(len(slist)):        url=slist[0]        title=slist[1]#访问图集        htm=requests.get(url)#正则获取图集的图片数量        picpage=re.search(r'<h1><span>.*?\(1/(\d+)\)</span></h1>',htm.text).group(1)        #组合拼接每张图片的图集名称,url地址,图片编号(用于下载后的文件重命名)添加到picurllistfor j in range(1,int(picpage)+1):if j==1:                picurllist.append([title,url,'{:03d}'.format(j)])else:                picurllist.append([title,url.replace('.html','_'+str(j)+'.html'),'{:03d}'.format(j)])    downpic(picurllist,words)
defdownpic(plist,dir):'''    :param plist: 每张图片的网页地址list    :param dir: 搜索关键词(用于最后保存图片时建立对应文件夹)    :return:     '''#判断存储目录是否存在,不存在则创建ifnot os.path.exists(savepath+dir):        os.mkdir(savepath+dir)#下载图片数    downCount=0for i in plist:#创建以每个图集作为名称的子目录ifnot os.path.exists(savepath+dir+'\\'+i[0]):            os.mkdir(savepath+dir+'\\'+i[0])        htm=requests.get(i[1])#正则匹配图片id        imgid=re.search(r'ar id=\'(.*?)\'',htm.text).group(1)#组合header中的referer        imgref=weburl+'/2020/down.html?picurl='+imgid#组合图片下载地址        imgurl='http://pic.jj20.com'+imgid        print(imgurl)#获取图片后缀名        filetype=imgid.split('.')[1]        header={"User-Agent":"Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36","Accept":"image/avif,image/webp,image/apng,image/*,*/*;q=0.8","Referer":imgref,            }#组合完整的图片保存路径        savepic='%s%s\\%s\\%s.%s' % (savepath,dir,i[0],i[2],filetype)#如果图片存在就跳过ifnot os.path.exists(savepic):#图片不存在则开始下载图片            pic = requests.get(imgurl, headers=header)#将图片文件写入指定位置with open(savepic, 'wb') as F:                F.write(pic.content)            downCount+=1#计算耗时    endtime=time.time()-start_time    print('任务完成! 共下载【%d】张图片,总耗时【%.2f】秒'%(downCount,endtime))
if __name__ == '__main__':    # 记录开始时间    start_time = time.time()# 存储路径    savepath = 'j:\\wallpaper\\'# search(分类id,搜索关键词,指定下载图集数)    search(243,'美女',100)

测试下载结果:

w15.jpg

w16.jpg

w17.jpg

图集我就不分享了,小伙伴们自己去下载吧。

B站:

https://www.bilibili.com/video/BV1Ef4y137by/

腾讯视频:

https://v.qq.com/x/page/x3268yvr44j.html

http://static.video.qq.com/TPout.swf?vid=x3268yvr44j&1314.swf

今天的分享就到这里结束啦!我们下期见咯~

END

w18.jpg
收藏、转发,点赞,安排一下?
您需要登录后才可以回帖 登录 | 注册

本版积分规则

精彩推荐
精彩推荐
热门资讯
热门资讯
网友晒图
网友晒图
图文推荐
图文推荐

QQ|小黑屋|Archiver|手机版|中国广告网 ( 鄂ICP备20005464号-17 )|网站地图

GMT+8, 2021-10-18 22:24

Powered by Discuz! X3.4

© 2001-2021 武汉掌媒科技有限公司