Python 爬取图虫网图片

作者: 奔跑的靖Ceo404 | 来源:发表于2017-11-10 17:08 被阅读59次

    关于&说明

    这是我的第一个正式的爬虫

    个人感觉图虫网的图片还是不错的,关键是小姐姐的图片多https://tuchong.com/tags/%E7%BE%8E%E5%A5%B3/

    此爬虫只作为学习交流,如有侵犯请告知作者,删除!、

    网站的爬取还是非常简单的没有模拟登陆,验证码,加密什么的个人感觉很简单

    准备

    开发环境&工具:Python3 ,Pycharm

    需要用到的模块 re,requests,os,json,urllib.parse,traceback

    分析

    进入官网我们选择发现-->标签然后会看到很多的类型

    标签.jpg

    我们先随意选择一个,这里我就选择美女这个标签吧!(小姐姐)

    进去之后我们会发现有很多的图片集

    美女.jpg

    如何获取图片

    第一种图片获取

    然后我们点击一个图片集,查看并且打开F12调试工具选择Network选项进行抓包,注意F12调试工具不要关闭后续有用!

    然后我在抓包数据中并没有找到准确的图片地址,但是可以从一下数据链接中找到图片的img_id(PS:img_id就是图片的标识例如https://photo.tuchong.com/1535376标识(这里是图片集的)/l/18389913(这里就是图片的标识了).jpg)我们在这里就不用这个了如果想用自行尝试,附上此数据链接地址 https://tuchong.com/rest/posts/15653079(后面的数字是本图片集的标识后续会讲到)

    image

    现在我们再去源码中找一下,应为网站js限制所以无法右击查看源码,请看下面讲解

    PS:
    如果你是谷歌内核的浏览器需要打开一个新标签且输入view-source:(这里填写链接就可以查看了)
    如果你是IE的话直接F12就可以了
    打开源码之后我们按快捷键Ctrl+F键打开快速搜索,在此时同样打开我们在此前图片页面打开的F12调试工具,且找到属于图片集内图片的链接

    image

    如图,然后复制图片链接,再次切换到源码查页在刚刚打开的Ctrl+F的搜索框中填入图片地址

    搜搜.png

    然后我们就找到所搜的图片集了,然后我们就可以在Pycharm写这一部分的代码:

    def Download(url):  # 下载网页
        head = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
        }#这里主要是进行简单的协议头伪装
        try:
            return requests.get(url, headers=head,timeout=60)
            #使用requests模块进行访问第一个参数是链接,第二个是协议头,第三个是超时时间!
    
        except (Exception, AttributeError) as a:
            print(a)
    
    

    这里我们首先定义一个HTTP访问下载然后我们先写一段正则

    <img id="image\d+" class="multi-photo-image" src="([a-zA-z]+://[^\s]*)" alt="">
    

    在后续我测试的时候,在匹配图片的时候我发现图虫网有两种图片显示方式所以我写的这个代码是两个不同的正则,当然如果你使用我们上面所找找到的img_id进行拼接的话就不用有下面的步骤了代码:

    def Picturenoe(title,url,page,type):#用正则匹配图片链接
    #第一个参数是后续获取到的图片记得名称,用做创建文件夹的名字,
    #第二个参数是我们传入图片集的地址例如https://tuchong.com/2602198/15653079
    #第三个参数是后为了直观输出的现在正在爬取第几页
    #第四个参数就是判断我们究竟该用那种方式进行匹配
        if type == 1:
            html = Download(url).text
            path = list(set(re.findall('<img id="image\d+" class="multi-photo-image" src="([a-zA-z]+://[^\s]*)" alt="">',html)))
    #我们第一种图片的正则匹配就是上面的type == 1的
        elif type == 2:
            html = Download(url).text
            path = list(set(re.findall('<img src="([a-zA-z]+://[^\s]*)" alt="\d+.[a-z]+" />', html)))
        Save(path,title,page)#这里的这个函数是后续写的图片下载保存
    #第二种才是上文的
    

    第二种图片获取

    那么我们在上文中提到了图片的两种显示方式,那么下面我们就讲解第二种的获取
    同上我还是查看源码并且我们需要打开F12调试工具并且点击左上角第一个图标



    点击之后我们再次点击页面中的图片我们会跳转到图片的代码处


    示范.gif

    我们复制图片链接接下来与第一种图片获取的查找一样打开搜索框搜索到图片搜之后复制改写为正则语句
    '<img src="([a-zA-z]+://[^\s]*)" alt="\d+.[a-z]+" />
    

    如果有不会正则的推荐正则表达式30分钟入门教程
    我们讲到这里图片的获取就讲完了,那么两种图片的获取有什么不同呢?
    1、先看浏览器显示的效果
    1.1图片集

    样式.jpg
    1.2文字加图片 样式二.jpg
    这是可以看到的区别那么他们主要的区别就是链接
    图片集:https://tuchong.com/2602198/15653079/
    文字图片混合排版:https://tuchong.com/1535376/t/15563899/
    在链接中可以很清晰的看到在后者多了一个/t/那么在我们后续的代码中就可以这么判断二者:
    def DownloadIf(url,title,page):
        if url.find("/t/") != -1:#如果没有找到就会返回-1
            Picturenoe(title,url,page,2)#这里的函数是调用我们上面的正则匹配的内个方法
        else:
            Picturenoe(title,url,page,1)
    

    至此我们的图片链接获取就结束了,开始我们下面的图片集链接的获取!

    图片集链接的获取

    1、分析&抓包

    1.1我在页面并没有找到底部有页数那么我们就可以向下啦当我们拉倒底部的时候,我们会看到有一个加载更多,由此我们就知道他是动态获取的所以我们就可以打开F12再次选择Network开始抓包


    点击完加载更多之后我们会发现第一个数据包是带有json的所以我们查看他的数据 页数.jpg
    在查看后我们会发现postlist这个节点有我们先要的数据链接 节点.png
    然后我们分析数据链接https://tuchong.com/rest/tags/%E7%BE%8E%E5%A5%B3/posts?page=5&count=20&order=weekly
    第一个参数其实是编码了的%E7%BE%8E%E5%A5%B3
    它解码之后就是美女也就是我们最开始选择的标签
    第二个是page从单词可疑看出他是页的意思,也就是现在你要获取第几页
    第三就是count每页需要获取多少个,一般为默认
    def Picturegroup(name,num):#获取第X页的列表
        url = "https://tuchong.com/rest/tags/%(name)s/posts?page=%(num)s&count=20&order=weekly" % {'name':name,"num":str(num)}
        html = Download(url)
        if html:
            return json.loads(html.text)#用json模块解析并且返回一个解析好的json模块
    

    图片集获取完

    标签的获取

    标签的获取其实很简单直接访问https://tuchong.com/explore/
    在源码中找到标签的代码

    <span class="tag-title">风光</span>
    

    用正则改写

    <span class="tag-title">([\u4e00-\u9fa5]+)</span>
    

    代码:

    def Thelabel():#获取开始的标签菜单
        url = "https://tuchong.com/explore/"
        html = Download(url).text
        return re.findall('<span class="tag-title">([\u4e00-\u9fa5]+)</span>',html)#匹配之后返回一个标签的列表
    

    在这个大概就完成了应为是图文教程所以没办法讲的很详细
    PS:这也是我第一次写文章可能有点啰嗦
    附上代码:

    # -*- coding:utf-8 -*-
    '''
    By:xiaojing
    Time:2017-11-1
    Blog:www.ceo404.com
    '''
    import requests
    import re
    import urllib.parse
    import json
    import traceback
    import os
    def Download(url):  # 下载网页
        head = {
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36",
        }
        try:
            return requests.get(url, headers=head,timeout=60)
    
        except (Exception, AttributeError) as a:
            print(a)
    def Thelabel():#获取开始的标签菜单
        url = "https://tuchong.com/explore/"
        html = Download(url).text
        return re.findall('<span class="tag-title">([\u4e00-\u9fa5]+)</span>',html)
    def Picturegroup(name,num):#获取第X页的列表
        url = "https://tuchong.com/rest/tags/%(name)s/posts?page=%(num)s&count=20&order=weekly" % {'name':name,"num":str(num)}
        print(url)
        html = Download(url)
        if html:
            return json.loads(html.text)
    def Save(url_list,title,page):#下载保存
        title_naem = os.path.join("picture",title)#要将图片保存到那个文件夹
        if not os.path.exists(title_naem):
            try:
                os.makedirs(title_naem)
                num = 0
                countfile = 0
                countdir = 0
                for url in url_list:
                    num += 1
                    path_name_split = url.split("/")
                    suffix = ".%s"%path_name_split[-1].split(".")[-1]
                    path_name = os.path.join("picture",os.path.join(title,"%s(%d)%s"%(title,num,suffix)))
                    #print(path_name)
                    #path_name = os.path.join("图虫网爬虫",path_name)
                    if not os.path.exists(path_name.encode()):
                        response = Download(url)
                        if requests:
                            with open(path_name,"wb") as f:
                                f.write(response.content)
                                f.close()
                                countfile +=  1
                                print("正在下载:%s 标题:%s   共%d张/现%d张"%(page,title,num,len(url_list)),"当前进度文件夹进度{0:.2f}%".format(countfile * 100 / len(url_list)))
                print("%s下载完毕!" % title)
            except:#输出错误的类型以及详细
                print(traceback.print_exc())
    def Picturenoe(title,url,page,type):#用正则匹配图片链接
        if type == 1:
            html = Download(url).text
            path = list(set(re.findall('<img id="image\d+" class="multi-photo-image" src="([a-zA-z]+://[^\s]*)" alt="">',html)))
        elif type == 2:
            html = Download(url).text
            path = list(set(re.findall('<img src="([a-zA-z]+://[^\s]*)" alt="\d+.[a-z]+" />', html)))
        Save(path,title,page)
        #print("开始下载:%s共:%d个" % (title, len(path)))
    def DownloadIf(url,title,page):
        if url.find("/t/") != -1:
            Picturenoe(title,url,page,2)
        else:
            Picturenoe(title,url,page,1)
    def strip(path):#删除Windows文件创建时不允许出现的字符
        return re.sub(r'[? .\\*|"<>,:/]',"",str(path))
    def initial(name,num):#总程序
        for i in range(1,num+1):
            print(i)
            img_info = Picturegroup(name,i)
            number = 0
            print("开始下载第%d页共:%d套" % (i,len(img_info['postList'])))
            for img_info_temp in img_info['postList']:
                img_info_url = img_info_temp['url']
                img_info_post_id = img_info_temp['post_id']
                img_info_title = strip(img_info_temp['title']).strip()
                if img_info_title =="":
                    img_info_title = img_info_post_id
                number += 1
                DownloadIf(img_info_url,img_info_title,"下载第%d页共:共%d套/现%d套" % (i,len(img_info['postList']),number))
        print("全部下载完毕共:%d页,%d套!"%(number,len(img_info['postList'])))
    if __name__ == '__main__':
        if not os.path.exists("picture"):
            os.makedirs("picture")
            print("偷偷创建了:picture 文件夹")
        label = Thelabel()#获取动态标签
        print("标签:",label,"更多标签请前往https://tuchong.com/explore/查询")
        name = urllib.parse.quote(input("请输入标签名字:"))
        number = int(input("请输入要爬取的页数:"))
        initial(name,number)
    
    
    演示一.jpg
    演示二.jpg
    演示四.jpg
    演示五.jpg
    演示六.jpg
    搞笑

    完2017年11月10日写

    相关文章

      网友评论

        本文标题:Python 爬取图虫网图片

        本文链接:https://www.haomeiwen.com/subject/pibbmxtx.html