掘金 后端 ( ) • 2024-04-17 10:46

theme: qklhk-chocolate

前言

每次写文章的封面不知道从哪里获取,每次都是去谷歌,百度搜索文章关键字 去找一些图,要么就是从代码运行结果找相关截图,总是找不到合适的文章图片显得乱糟糟的,又没有找到相关的项目能够根据关键字生成文章封面,今天就要到了一个另类的方法,用爬虫获取 必应(Bing)搜索引擎首页每日的高清大图。

开始

访问bing.com

微信截图_20240416230343.png 很简单就能发现图片的请求地址隐藏到了网页里面

image.png 通过网页找图片的关键的方法是有水印的,而且图不是高清的

image.png

最后通过GitHub找到一个公开的接口: https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=ZH-CN

直接访问就能拿到高清无水印图片的地址文本内容,稍微做一下解析就行

image.png 接下来就简单写一下爬虫代码

# 下载并存储Bing每日壁纸到指定位置


import os
import re
import requests
from io import BytesIO
from PIL import Image
import shutil

class BingUHD(object):

    def __init__(self):
        # 默认bing图片查询地址
        self.url = 'https://cn.bing.com/HPImageArchive.aspx?format=js&idx=0&n=1&mkt=ZH-CN'
        self.path = './BingUHD/'
        self.headers = {
            'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) '
                          'Chrome/80.0.3987.132 Safari/537.36'
        }
        self.resolution = 'UHD'

    # 取得图片相关信息
    def get_img_info(self):
        try:
            # 获取图片信息
            result = requests.get(self.url, headers=self.headers).json()
            # 提取图片地址
            raw_img_url = 'https://cn.bing.com' + result['images'][0]['url']
            # 得到默认图片链接
            normal_img_url = raw_img_url[0:raw_img_url.find(".jpg") + 4]
            # 得到UHD图片链接替换默认的 1080 图片为UHD图片链接
            uhd_img_url = normal_img_url.replace("1920x1080", self.resolution)
            # 提取中文标题和版权信息
            date = result["images"][0]["startdate"]
            title = result["images"][0]["title"]
            copy_right = result["images"][0]["copyright"]

            return normal_img_url, uhd_img_url, date, title, copy_right

        except Exception as e:
            print('错误: 无法获取到图片地址,请检查网络连接' + '\n')

    def img_download(self,url,file_name):
        try:
            response = requests.get(url, stream=True)

            if response.status_code == 200:
                with open(file_name, 'wb') as f:
                    response.raw.decode_content = True
                    shutil.copyfileobj(response.raw, f)
                print(file_name+"图片下载成功")
            else:
                print(file_name+"无法下载图片")
        except Exception as e:
            print('错误: 无法下载图片,请检查网络连接' + '\n')

    # 得到今日图片信息并清洗
    def get_today_img_download(self,file_name):
        try:
            info = self.get_img_info()
            normal_url = info[0]
            uhd_url = info[1]

            

            # 图片分辨率文字
            # normal = normal_url[(normal_url.rfind("_") + 1): -4]
            # uhd = uhd_url[(uhd_url.rfind("_") + 1): -4]

            # 图片分辨率文字
            normal = self.get_pic_size()[0]
            uhd = self.get_pic_size()[1]
            self.img_download(normal_url,file_name+normal+'.jpg')
            self.img_download(uhd_url,file_name+uhd+'.jpg')
        except Exception as e:
            print('错误: 无法获取到图片信息,请检查网络连接' + '\n')


    # 取得文件名称
    def get_file_name(self):
        try:
            info = self.get_img_info()
            # 定义文件夹
            file_path = self.path + info[2][0:4] + '-' + info[2][4:6] + '/'
            # 判断文件夹是否存在
            if not os.path.exists(file_path):
                os.makedirs(file_path)
            # 定义文件名
            copy_right = info[4]
            copy_right = copy_right[0:copy_right.find(' ')]
            # 绝对路径
            name = info[2] + '.' + info[3] + '.' + copy_right + '.'
            full_name = file_path + name

            return full_name
        except Exception as e:
            print('错误: 无法获取到图片信息,请检查网络连接' + '\n')

    # 取得图片的尺寸
    def get_pic_size(self):
        """
        获取远程图片的尺寸
        :return:
        """
        size_list = []
        url = [self.get_img_info()[0], self.get_img_info()[1]]
        for u in url:
            r = requests.get(u)
            img = Image.open(BytesIO(r.content))
            pic_size = str(img.width) + 'x' + str(img.height)
            size_list.append(pic_size)
        return size_list

    # 取得今日美图文字
    def get_description(self):
        url = 'https://www.bing.com/?mkt=zh-CN'
        rsp = requests.get(url)
        result = re.search(r'({"Description":")(.*?)(","Image")', rsp.text).group(2)
        return result


if __name__ == "__main__":
    bing = BingUHD()
    file_name = bing.get_file_name()
    content = bing.get_today_img_download(file_name)

进入脚本根目录执行python脚本就能自动创建相关的文件夹,自动下载图片,项目结构内容如下:

image.png

最后

后面文章找不到封面我就拿这个做文章封面了,上面的代码通过已知隐藏的接口获取到了更高清图片的3140*2160 4K图片地址,看上图中的两种图片体积可以看出来,图片质量完全不一样。

可能对于Python 新手有些不友好,如果不抗拒一段段代码复制去询问ChatGPT 然后自己慢慢打印调试尝试,其实有那种精神就能慢慢学会了,站在技术实现的角度其实直接从F12控制台就能找到这个图片的源地址右键就能保存了,我的想法是后面有机会的话做一个图片展示的网站,尝试部署这个脚本用定时任务自动爬取收集这些图片,就不用特地手动运行脚本了。