【Python机器人】利用Selenium自动上传图片(以此示例展示Python在处理文件、运行js的能力)

-

①利用到的知识点:

1. 遍历文件夹+遍历文件夹下的所有文件名(文件名带格式);

2. 根据图片像素判断判断图片图片和不合规(使用扩展:from PIL import Image  # pip install pillow);

3. 创建文件夹+移动文件(使用扩展:import shutil)

3. Selenium的自动点击+自动填写input+Selenium运行js能力(可运行jQ<这里能运行jQ就很好操作dom>、原生js);

4. 写Excel(使用扩展:import openpyxl  # pip install openpyxl);

5. 切换iframe来操作iframe里面的dom。

②搭建开发环境:

可参考此博文上半段,已经很详细:https://blog.csdn.net/weixin_41827162/article/details/86165615

------------------------------

0)python3.6+环境。

1)pip install --user -U selenium
2)下载对应版本或者对应win系统的
     Geckodriver:https://npm.taobao.org/mirrors/geckodriver 下载最新驱动即可。
     将文件解压后的exe一同放在D://python/driver目录(没有的话手动创建一个即可,exe都放在这里可以只添加一个path即可解决所有浏览器driver)。
   并将'D:\\python\\driver'路径直接添加在path环境中。
3)重启电脑
4)测试是否安装成功:
      print("hello")
      from selenium import webdriver
      browser = webdriver.Firefox()      # 打开浏览器
      browser.get('http://www.baidu.com/')   # 打开页面
     如果chrome浏览器或者Firefox浏览器能自动打开了百度就证明成功。

     推荐使用火狐浏览器(2018版以后应该都可以,如果可以,就请使用最新版即可)来操作。

------------------------------

③整个源代码:

A. 上传图片,并记录到Excel里面:

# 《自动上传图片素材程序》
# 单线程运行,同时每次大操作点击后都设置了延时,防止程序拖垮服务器。
# 此网站经常性发生卡顿状况,建议sleep时间拉长。
# 如果报“图片已上传”,则是因为同一文件夹和同一张图片被再次上传


from selenium import webdriver
import time
import os
import openpyxl  # pip install openpyxl
import datetime
from PIL import Image  # pip install pillow
import shutil
import random


# 写入Excel数据
def write_excel(_one_name, _two_name, img_name, that_img_path, img_url):
    print('将数据写入Excel')
    print([_one_name, _two_name, img_name, that_img_path, img_url])

    # 打开excel文件
    wb = openpyxl.load_workbook('./excel/nipic-img-price.xlsx')
    ws = wb.active

    # 获取最大行
    the_max_row = ws.max_row
    # 下一行为最新行
    the_index = the_max_row + 1

    # 填充
    ws['A' + str(the_index)] = str(img_name)
    ws['B' + str(the_index)] = str(_one_name)
    ws['C' + str(the_index)] = str(_two_name)
    ws['D' + str(the_index)] = str(img_url)
    ws['E' + str(the_index)] = str(datetime.datetime.now())
    ws['F' + str(the_index)] = str(that_img_path)

    # 保存
    wb.save('./excel/nipic-img-price.xlsx')

    print('此行保存完成')

    pass


# 上传图片
def upload_img(driver, _one_name, _two_name, that_img_path, _img_name):
    print('选择本次需要上传的图片')
    print('===img===' + that_img_path)
    print('===img_name===' + _img_name)

    # 直接赋值一张图片
    print('赋值图片文件,并等待')
    driver.find_element_by_name('upload1').send_keys(that_img_path)
    time.sleep(15)
    print('等待完成')

    # 延时等待上传后打开已上传列表
    print('打开已上传列表')
    driver.get('http://user.nipic.com/photo/pendings')
    time.sleep(1)

    # 手动生成封面
    js = '$(".J_works_manual").eq(0).click()'
    driver.execute_script(js)
    time.sleep(10)

    # 获取该文件编辑的id网址
    print('拿到id网址')
    # js = 'let k_href = "http://user.nipic.com" + $(".J-works-edit").eq(0).data("href"); window.location.href=k_href;'
    # driver.execute_script(js)
    href = driver.find_element_by_class_name('J-works-edit').get_attribute('data-href')
    print(href)
    if href is None:
        print('目标图片ID网址为空,已挑过')
        pass
    else:
        img_url = 'http://user.nipic.com' + href
        print(img_url)

        # 其他
        # write_img_info(driver, _one_name, _two_name, href)
        # 往Excel写内容
        write_excel(_one_name, _two_name, _img_name, that_img_path, img_url)

        pass
    pass


# 进入用户后台
def into_user_center(_browser, _one_name, _two_name, that_img_path, _img_name):
    print([_one_name, _two_name, that_img_path, _img_name])
    print('进入用户后台')

    # 进入上传图片的假页面
    print('进入进入上传图片的假页面')
    _browser.get('http://user.nipic.com/upload/index1')
    time.sleep(1)

    # 关闭协议
    print('尝试关闭协议弹窗')
    _browser.find_element_by_class_name('J-confirm-yes').click()
    time.sleep(1)

    # 直接打开到iframe网址
    iframe1_src = _browser.find_element_by_id('normalUploadIframe').get_attribute('src')
    print(iframe1_src)
    if iframe1_src is None:
        print('参数为空1,已挑过操作')

        pass
    else:
        # 打开iframe网址
        _browser.get(iframe1_src)
        time.sleep(2)

        # print('切换iframe对象')
        iframe = _browser.find_element_by_id('uploadIframeBox')
        _browser.switch_to.frame(iframe)
        time.sleep(1)

        # 测试是否一级切换
        print('测试是否已经切换')
        try:
            the_type = _browser.find_element_by_id('upload1').get_attribute('type')
            print(the_type)
            if the_type:
                print('iframe对象切换成功')
                # 其他操作
                upload_img(_browser, _one_name, _two_name, that_img_path,_img_name)

                pass
            else:
                print('iframe对象切换失败2')
                pass
            pass
        except:
            print('iframe对象切换失败1')
            pass

        pass

    pass


# 登录
def login(_browser, _one_name, _two_name, that_img_path, _img_name):
    print([name, pwd])
    print('准备密码登录')
    time.sleep(1)

    print('正在自动填写账号、密码')
    _browser.find_element_by_id('UserName').send_keys(name)
    time.sleep(1)

    _browser.find_element_by_id('PassWord').send_keys(pwd)
    time.sleep(1)

    print("模拟点击登录按钮")
    _browser.find_element_by_class_name('new-login-btn').click()
    time.sleep(3)  # 注意,此网站自身登录比较慢,可能是做了后端的安全校验,此处等待3s。

    print('完成登录')
    into_user_center(_browser, _one_name, _two_name, that_img_path, _img_name)

    pass


# 读取所有文件夹
def readfile(filePath):
    print(filePath)
    return os.listdir(filePath)

    pass


# 读取所有文件名
def file_name(_browser, file_dir, _one_name, _two_name):
    for root, dirs, files in os.walk(file_dir):
        for f in files:  # 遍历所有文件
            print('单张图片参数获取完成,f=' + str(f))
            # 一级目录名
            print(_one_name)
            # 二级目录名
            print(_two_name)
            # 图片绝对路径
            that_img_path = file_dir + '\\' + f
            print(that_img_path)

            # 其他
            print([_one_name, _two_name, that_img_path])

            # 判断图片是否规格合适,不合规就移动到新文件夹
            filename = str(that_img_path)
            img = Image.open(filename)
            imgSize = img.size  # 图片的长和宽
            maxSize = max(imgSize)  # 图片的长边
            minSize = min(imgSize)  # 图片的短边
            print([maxSize, minSize])
            if maxSize < 500 and minSize < 500:  # 不符合像素规格时,单位:像素
                print('该图片像素不符合,已挑过')
                save_file_path = save_file + _one_name + '\\' + _two_name  # 新文件夹
                if not os.path.exists(save_file_path):
                    os.makedirs(save_file_path)  # 创建新文件夹,没有则创建该多级文件夹
                    pass
                else:
                    print('同名文件夹已存在')
                    pass
                try:
                    shutil.move(that_img_path, save_file_path)  # 移动文件
                    pass
                except:
                    print('同名文件已存在')
                    pass

                pass
            else:
                # 打开浏览器
                _browser = webdriver.Firefox()

                # 打开网页
                print('打开网页')
                _browser.get(
                    'https://login.nipic.com/?backurl=http://www.nipic.com/')
                _browser.implicitly_wait(2)  # 隐式等待
                login(_browser, _one_name, _two_name, that_img_path, f)

                time.sleep(0.1)
                pass

            pass

        time.sleep(0.1)
        pass

    pass


# 必要参数设置
# 参数自定义
name = 'xxx'  # 账号
pwd = 'xxxxxx'  # 密码
path = 'D:\\python38\\nipic.com\\图片素材\\原创非商业共享\\'  # 图片文件夹根目录(一级目录的根目录)
save_file = 'D:\\python38\\nipic.com\\不合格像素图片\\原创非商业共享\\'

# 全局浏览器对象
browser = ''

# 程序入口
if __name__ == '__main__':
    print('启动程序')

    # 读取图片路径
    # 有多少一级目录、二级目录、图片,在程序不中断的情况下,都会扫描到,一次性全部单线程上传
    print('读取图片文件')
    one_file_name_array = readfile(path)
    for one_name in one_file_name_array:  # 一级目录
        # print(one_name)

        two_file_name_array = readfile(path + one_name)
        for two_name in two_file_name_array:  # 二级目录
            # print(two_file_name_array)

            # 其他
            _path = path + one_name + '\\' + two_name
            # print(_path)
            file_name(browser, _path, one_name, two_name)

            time.sleep(0.1)
            pass

        time.sleep(0.2)
        pass

    pass

    print('程序运行完成')
pass

B. 读取Excel,点选多级下拉菜单,展示jQ应用能力:

# 《为图片自动填写信息》


from selenium import webdriver
import time
import os
import openpyxl
import datetime
from openpyxl import Workbook
import random


# 信息填写
# 参数自定义
def write_img_info(driver, _one_name, _two_name, _img_name, _img_url, _author_name, _title, _keyword, _price, _intro):
    print('开始填写图片信息')
    print('非必填项全部省略')
    print([_one_name, _two_name, _img_name, _img_url, _author_name, _title, _keyword, _price, _intro])

    # 点击 零级分类,选择 设计
    print('选择 设计')
    zero_name = '设计'
    js = '$(".J-false-select").eq(0).click();'
    driver.execute_script(js)
    time.sleep(0.5)
    js = 'let z_txt="' + zero_name + '";let k_a=$(".false-droplist-box-item");for(let i=0; i

C. 其他说明:

  • 为了防止长期吃牢饭,建议加好延时,运行单线程。如果想要多线程,建议复制多个项目目录,运行多个程序;
  • 本程序在参数传递中,有待优化(因为为了让pycharm尽量不出现波浪线、标记点、一些参数传递使用的不够优美);
  • 所有程序用到的知识点、功能点还是比较简单的,但是它们展示和记录了程序的具体用法和具体关联。
  • 程序凡是遇到错误应该告知或根据条件判断跳过错误点。

 

D. 项目文件分部:

Excel文件表头,A1行的字段,A1字段必须有:

文件夹放置:

【Python机器人】利用Selenium自动上传图片(以此示例展示Python在处理文件、运行js的能力)_第1张图片

-

-

你可能感兴趣的:(【Python机器人】利用Selenium自动上传图片(以此示例展示Python在处理文件、运行js的能力))