zoukankan      html  css  js  c++  java
  • 回车桌面图片爬取

    回车桌面图片爬取

    今天我们就来爬爬这个网站 https://tu.enterdesk.com/ 这个网站能爬的资源还是很多的,但我就写一个例子,其他的可以根据思路去写。

    首先还是先来分析下这个网站的图片获取过程
    enter description here

    我选择的是图库,先随便选择一个标签,我这选宠物吧
    enter description here

    哟,我们再看看有没有翻页 开启F12(开发者工具)

    用不习惯火狐,还是开谷歌来看吧
    enter description here

    那么就访问看看?随便选取一个访问看看是不是能出图片
    https://tu.enterdesk.com/chongwu/6.html

    结果肯定是可以的啦

    问题来了,现在怎么查看最后一页的页码是什么?一种是无限循环下去 直到 没有图片标签的时候报错,还有一种就是从源码中找出页码 那就得看有没有页码按钮 刚才滚轮比较快 现在慢一点 看有没有页码这些东西
    enter description here

    这网站还是有页码的,那说明在html源码中能找到页码数

    两种方法:
    F12工具选择元素
    enter description here

    Ctrl+U走一波 源代码直接搜索
    enter description here

    现在找到所有页码,接下来就是分析图片源地址了
    enter description here

    选择目标图片看看是不是源地址 原图 打开一看其实不是
    https://up.enterdesk.com/edpic_360_360/4c/3e/c2/4c3ec2be7061121ad5994a9b51241fa3.jpg

    现在再点击进去图片里面 发现是原图了 这时再选择图片查看标签的图片链接
    enter description here

    复制上图里面的链接 打开一看就是原图啦 看下图的链接 怎么那么熟悉?
    enter description here

    对比下两个链接
    https://up.enterdesk.com/edpic_360_360/4c/3e/c2/4c3ec2be7061121ad5994a9b51241fa3.jpg

    https://up.enterdesk.com/edpic_source/4c/3e/c2/4c3ec2be7061121ad5994a9b51241fa3.jpg

    略缩图 edpic_360_360
    原图 edpic_source

    这下整体思路就有啦,我们可以获取略缩图的链接将url进行重构,形成原图链接,然后再批量下载就好啦!

    开始撸代码了!!!

    第一个是 class Spider(): 我们声明了一个类,然后我们使用 def __init__去声明一个构造函数

    import requests
    all_urls = []  # 我们拼接好的每一页链接
    
    class Spider():
        # 构造函数,初始化数据使用
        def __init__(self, target_url, headers):
            self.target_url = target_url
            self.headers = headers
    
        # 获取所有的想要抓取的URL
        def getUrls(self):
            #获取末页
            response = requests.get(target_url % 1,headers=headers).text
            html = BeautifulSoup(response,'html.parser')
            res = html.find(class_='wrap no_a').attrs['href']  #找到末页的标签提取末页的链接
            page_num = int(re.findall('(d+)',res)[0])  #正则匹配 页码数
            global all_urls
            # 循环得到拼接URL
            for i in range(1, page_num + 1):
                url = self.target_url % i
                all_urls.append(url)
    

    分析怎么提取末页链接如下图:
    enter description here

    这里我们采用多线程的方式爬取,引入下面几个模块

    from bs4 import BeautifulSoup #解析html
    import threading #多线程
    import re #正则匹配
    import time #时间
    

    新增加一个全局的变量,而且是多线程操作,我们需要引入线程锁,避免资源同时写入出错。

    all_img_urls = []       #所有图片链接
    g_lock = threading.Lock()  #初始化一个锁
    

    声明一个Producer的类,负责提取图片链接,然后添加到 all_img_urls 这个全局变量中

    class Producer(threading.Thread):
    
        def run(self):
            headers = {
                'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0'
            }
            global all_urls
            while len(all_urls) > 0:
                g_lock.acquire()  # 在访问all_urls的时候,需要使用锁机制
                page_url = all_urls.pop(0)  # 通过pop方法移除第一个元素,并且返回该值
                g_lock.release()  # 使用完成之后及时把锁给释放,方便其他线程使用
                try:
                    print("分析" + page_url)
                    response = requests.get(page_url, headers=headers, timeout=3).text
                    html = BeautifulSoup(response,'html.parser')
                    pic_link = html.find_all(class_='egeli_pic_li')[:-1]
                    global all_img_urls
                    g_lock.acquire()  # 这里还有一个锁
                    for i in pic_link:
                        link = i.find('img')['src'].replace('edpic_360_360','edpic_source')
                        all_img_urls.append(link)
                    g_lock.release()  # 释放锁
                    # time.sleep(0.1)
                except:
                    pass
    

    线程锁,在上面的代码中,当我们操作all_urls.pop(0)的时候,我们是不希望其他线程对他进行同时操作的,否则会出现意外,所以我们使用g_lock.acquire()锁定资源,然后使用完成之后,记住一定要立马释放g_lock.release(),否则这个资源就一直被占用着,程序无法进行下去了。

    if __name__ == "__main__":
    
        headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0'
        }
    
        target_url = 'https://tu.enterdesk.com/chongwu/%d.html'  # 图片集和列表规则
    
        print('开始获取所有图片页链接!!!')
        spider = Spider(target_url, headers)
        spider.getUrls()
        print('完成获取所有图片页,开始分析图片链接!!!')
    
        threads = []
        for x in range(10):
            gain_link = Producer()
            gain_link.start()
            threads.append(gain_link)
    
        # join 线程同步 主线程任务结束之后 进入阻塞状态 等待其他的子线程执行结束之后 主线程在终止
        for tt in threads:
            tt.join()
    

    下面再定义一个DownPic类 用于下载图片

    class DownPic(threading.Thread):
        
        def run(self):
            headers = {
                'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0'
            }
            while True:
                global all_img_urls
                # 上锁
                g_lock.acquire()
                if len(all_img_urls) == 0:  # 如果没有图片了,就解锁
                    # 不管什么情况,都要释放锁
                    g_lock.release()
                    break
                else:
                    t = time.time()
                    down_time = str(round(t * 1000))  # 毫秒级时间戳
                    pic_name = 'D:\test\'+ down_time + '.jpg'
                    pic = all_img_urls.pop(0)
                    g_lock.release()
                    response = requests.get(pic, headers=headers)
                    with open(pic_name, 'wb') as f:
                        f.write(response.content)
                        f.close()
                    print(pic_name + '   已下载完成!!!')
    

    可以看到利用了down_time = str(round(t * 1000)) 来生成毫秒级时间戳来命名图片 其实也可以获取图片的名称来命名 那就靠自己去写一个了

    再从if __name__ == "__main__": 添加下面代码 用于开启多线程下载

     print('分析图片链接完成,开始多线程下载!!!')
        for x in range(20):
            download = DownPic()
            download.start()
    

    整体流程就这么写完啦!run下代码
    enter description here

    Tips:跑这个代码需要在D盘创建test文件夹 或者自己修改代码实现其他功能

    附出完整代码:

    import requests
    from bs4 import BeautifulSoup #解析html
    import threading #多线程
    import re #正则匹配
    import time #时间
    
    
    all_urls = []  # 我们拼接好的每一页链接
    all_img_urls = []       #所有图片链接
    g_lock = threading.Lock()  #初始化一个锁
    
    class Spider():
        # 构造函数,初始化数据使用
        def __init__(self, target_url, headers):
            self.target_url = target_url
            self.headers = headers
    
        # 获取所有的想要抓取的URL
        def getUrls(self):
            #获取末页
            response = requests.get(target_url % 1,headers=headers).text
            html = BeautifulSoup(response,'html.parser')
            res = html.find(class_='wrap no_a').attrs['href']  #找到末页的标签提取末页的链接
            page_num = int(re.findall('(d+)',res)[0])  #正则匹配 页码数
            global all_urls
            # 循环得到拼接URL
            for i in range(1, page_num + 1):
                url = self.target_url % i
                all_urls.append(url)
    
    
    #负责提取图片链接
    class Producer(threading.Thread):
    
        def run(self):
            headers = {
                'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0'
            }
            global all_urls
            while len(all_urls) > 0:
                g_lock.acquire()  # 在访问all_urls的时候,需要使用锁机制
                page_url = all_urls.pop(0)  # 通过pop方法移除第一个元素,并且返回该值
                g_lock.release()  # 使用完成之后及时把锁给释放,方便其他线程使用
                try:
                    print("分析" + page_url)
                    response = requests.get(page_url, headers=headers, timeout=3).text
                    html = BeautifulSoup(response,'html.parser')
                    pic_link = html.find_all(class_='egeli_pic_li')[:-1]
                    global all_img_urls
                    g_lock.acquire()  # 这里还有一个锁
                    for i in pic_link:
                        link = i.find('img')['src'].replace('edpic_360_360','edpic_source')
                        all_img_urls.append(link)
                    g_lock.release()  # 释放锁
                    # time.sleep(0.1)
                except:
                    pass
    
    
    class DownPic(threading.Thread):
        
        def run(self):
            headers = {
                'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0'
            }
            while True:
                global all_img_urls
                # 上锁
                g_lock.acquire()
                if len(all_img_urls) == 0:  # 如果没有图片了,就解锁
                    # 不管什么情况,都要释放锁
                    g_lock.release()
                    break
                else:
                    t = time.time()
                    down_time = str(round(t * 1000))  # 毫秒级时间戳
                    pic_name = 'D:\test\'+ down_time + '.jpg'
                    pic = all_img_urls.pop(0)
                    g_lock.release()
                    response = requests.get(pic, headers=headers)
                    with open(pic_name, 'wb') as f:
                        f.write(response.content)
                        f.close()
                    print(pic_name + '   已下载完成!!!')
    
    
    if __name__ == "__main__":
    
        headers = {
            'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64; rv:52.0) Gecko/20100101 Firefox/52.0'
        }
    
        target_url = 'https://tu.enterdesk.com/chongwu/%d.html'  # 图片集和列表规则
    
        print('开始获取所有图片页链接!!!')
        spider = Spider(target_url, headers)
        spider.getUrls()
        print('完成获取所有图片页,开始分析图片链接!!!')
    
        threads = []
        for x in range(10):
            gain_link = Producer()
            gain_link.start()
            threads.append(gain_link)
    
        # join 线程同步 主线程任务结束之后 进入阻塞状态 等待其他的子线程执行结束之后 主线程在终止
        for tt in threads:
            tt.join()
    
        print('分析图片链接完成,开始多线程下载!!!')
        for x in range(20):
            download = DownPic()
            download.start()
    
    作者:YinJay

  • 相关阅读:
    类型参数化
    scala 集合类型
    scala 列表List
    统计HDFS 上字节数据统计
    用scala 实现top N 排名
    scala 基础笔记
    Java 设计模式之 装饰者模式
    通过java api 读取sql 中数据(查询)
    leetcode 34. Search for a Range
    canvas画简单电路图
  • 原文地址:https://www.cnblogs.com/YinJay/p/10926003.html
Copyright © 2011-2022 走看看