记一次失败的使用python selenium刷课学习通脚本(细节满满)+关于使用selenium的疑难杂症解决+json数据请求的疑难杂症+py冷门知识

目录

源代码

写脚本的一些知识点

关于部分网页无法找到元素的问题1

问题描述

解决方案

方案1

方案2

关于部分网页无法找到元素的问题2

问题描述

解决方案

被网站检查出来我们使用了selenium了怎么办?

问题描述

解决方法

如何实现前进后退

当使用py删除文件时报禁止访问怎么办

怎么使用py实现解压文件?

怎么打开系统的图片应用向用户展示图片?

代码

效果展示

怎么去下载网络资源?

下载网络资源

下载网页

怎么获取当前路径?

怎么使用Webderive截图?

JSON数据的天坑?

最后的一些未解决的问题


一周上6天,还凭空给我们又塞了两门网课(软件测试,UML建模)妈妈呀,不让人活了!!

于是就有了了这个刷课脚本,最后的效果不是太好,但是已基本实现

源代码

先上源码,应该是可以直接运行的,不过只是针对与我们这门网课

import platform
import os
import random
import zipfile
import shutil
import requests
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.edge.service import Service
from selenium.webdriver.edge.options import Options
import time
from win32com.client import Dispatch

def init(driverfilename, isHeadless):
    print("开始浏览器初始化\n")
    # 创建option对象
    options = Options()
    if isHeadless:
        # 设置无头模式即浏览器不弹出,只在后台运行
        options.add_argument("headless")
    # 解决部分网站的对于Selenium的js监测机制,
    # 以下2行
    options.add_experimental_option('excludeSwitches', ['enable-automation'])
    options.add_experimental_option('useAutomationExtension', False)
    # 加载浏览器驱动
    Webdriver = Service(driverfilename)
    # 加载驱动和无头
    driver = webdriver.Edge(service=Webdriver, options=options)
    # 解决部分网站的对于Selenium的js监测机制,
    # 以下1行
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",
                           {'source': 'Object.defineProperty(navigator,"webdriver",{get:()=>undefind})'})
    print("浏览器初始化完成")

    return driver


def getversion(filename):
    parser = Dispatch("Scripting.FileSystemObject")
    version = parser.GetFileVersion(filename)
    print("当前Edge浏览器版本为:"+version)
    return version


def getEdgePath():
    while True:
        print("""
        请输入您的Edge浏览器的源路径(不是快捷方式的路径)
        方法:
        1 找到桌面上的Edge浏览器,右击鼠标选择“打开文件位置”
        2 进入新打开的文件夹之后找到“msedge.exe”文件右击复制文件路径
        3 将刚刚复制的路径,复制过来即可
        """)
        path1=input("")
        if path1!="":
            return path1
        else:
            print("请输入Edge浏览器的源路径")


def showimg(path):
    userPlatform = platform.system()  # 获取操作系统
    if userPlatform == 'Windows':  # Mac
        os.startfile(path)
    else:
        print("暂且不支持您的操作系统")

def login(Driver, inithtml):
    # 请求
    Driver.get(inithtml)
    # 截图
    path = "code1.png"
    Driver.save_screenshot(path)
    showimg(path)
    print("请在15s内用学习通扫码,注意会弹出相片,请扫描相片上的二维码")

def getfirstpage(Driver, listinfo):
    # 初始化章节
    topic = listinfo[0]
    section = listinfo[1]
    # 寻找第一层框架入口
    s = Driver.find_element(By.ID, "frame_content").get_attribute("src")
    # 进入第一层框架入口
    Driver.get(s)
    time.sleep(1.2)
    # 获取UML这门课的位置
    UML = Driver.find_element(By.XPATH, '//*[@id="course_229314406_65132055"]/div[1]')
    # 进入这门课
    UML.click()
    time.sleep(1.2)
    # 获取当前句柄,这很重要!!
    url = Driver.window_handles
    # 跳转到我们需要的网页
    Driver.switch_to.window(url[1])
    # 寻找回到旧版入口
    t1 = Driver.find_element(By.XPATH, '/html/body/div[1]/div[1]/div/a')
    # 进入回到旧版
    t1.click()
    time.sleep(1.2)
    # 获取当前句柄,这很重要!!
    url = Driver.window_handles
    # 跳转到我们需要的网页
    Driver.switch_to.window(url[1])
    getdiv = Driver.find_elements(By.CLASS_NAME, "units").__len__()
    for az in range(topic, getdiv):
        y = Driver.find_element(By.XPATH, "/html/body/div[5]/div[1]/div[2]/div[3]/div[" + str(az) + "]").find_elements(
            By.CLASS_NAME, "clearfix").__len__()
        if (section <= y):
            for i in range(section, y + 1):
                # Driver.switch_to.window(url[1])
                newpage = Driver.find_element(By.XPATH,
                                              "/html/body/div[5]/div[1]/div[2]/div[3]/div[" + str(az) + "]/div[" + str(
                                                  i) + "]")
                time.sleep(1)
                newpage.click()
                try:
                    # 再次进入框架
                    iframe3 = Driver.find_element(By.XPATH, '//*[@id="iframe"]').get_attribute("src")
                    Driver.get(iframe3)
                    time.sleep(1.2)
                    # 加载播放按钮
                    firstTopic = Driver.find_element(By.XPATH, '//*[@id="ext-gen1046"]/iframe')
                    # 开始播放
                    firstTopic.click()
                    print("正在观看弟" + str(topic)+"章 第"+str(section)+"节视频" )
                    time1=MovieTime()
                    print("弟" + str(topic) + "章 第" + str(section) + "节视频观看完毕,耗时"+str(time1)+"秒")
                except:
                    print("正在浏览弟" + str(topic)+"章 第"+ str(section) + "节PPT或文档\n")
                    time2=PPTTime()
                    print("弟" + str(topic) + "章 第" + str(section) + "节PPT浏览完毕,耗时"+str(time2)+"秒")
                time.sleep(2)
                # 回到上一个页面
                Driver.back()
                # 再点击返回回到刷课页
                return1 = Driver.find_element(By.XPATH, "/html/body/div[3]/div/div[1]/a")
                return1.click()
                time.sleep(2)
        else:
            print("没有弟" + str(topic) + "章,没有弟" + str(section) + "节\n已自动跳转到下一章")
        section = 1
    x=input("当前课程已刷取完毕,感谢使用,更多脚本定制联系2872392768")
def isHeadless():
    while True:
        isHeadless = input("是(Y)否(N)开启后台模式")
        if (isHeadless == "Y" or isHeadless == "N"):
            if isHeadless == "Y":
                return True
            else:
                return False
        else:
            print("请输入正确指令")


def getTopicInfo():
    listinfo = []
    while True:
        topicStr = input("请输入从第几章开始:(1~23)")
        try:
            topic = int(topicStr)
            if (topic >= 1 and topic <= 23):
                listinfo.append(topic)
                break
            else:
                print("请输入合法参数")
        except:
            print("请输入合法参数")
    while True:
        topicSectionStr = input("请输入从本章的第几节开始:(0到10)")
        topicSection = int(topicSectionStr)
        try:
            topic = int(topicStr)
            if (topicSection >= 0 and topicSection <= 10):
                listinfo.append(topicSection)
                break
            else:
                print("请输入合法参数")
        except:
            print("请输入合法参数")
    return listinfo


def MovieTime():
    sleep1=random.uniform(300, 600)
    print("本节将播放"+str(sleep1)+"秒")
    time.sleep(sleep1)
    return sleep1

def PPTTime():
    sleep1=random.uniform(3, 10)
    print("本节将浏览"+str(sleep1)+"秒")
    time.sleep(sleep1)
    return sleep1


def downloadandZip(downloadurl, headers, name):
    try:
        # 驱动下载
        print("正在下载驱动")
        dow = requests.get(downloadurl, headers)
        open("drive.zip", "wb").write(dow.content)
        print("驱动下载完成,正在解压")
        # 文件解压
        with zipfile.ZipFile(name) as zf:
            zf.extractall()
        print("解压完成")
        return True
    except:
        return False


def startDownloadandZipexc(downloadurl, headers):
    name = "drive.zip"
    temp1 = "Driver_Notes"
    downloadandZip(downloadurl, headers, name)
    # 删除无关文件
    print("正在删除无关文件")
    drivername = "msedgedriver.exe"
    if os.path.exists(temp1):
        shutil.rmtree(temp1)
    if os.path.exists(name):
        os.remove(name)
    print("无关文件删除成功")
    if os.path.exists(drivername):
        return os.getcwd() + "\msedgedriver.exe"
    else:
        while True:
            t = input("浏览器驱动受损或被删除,是(Y)否(N)重新下载")
            if t == "Y" or t == "N":
                if t == "Y":
                    # 驱动下载
                    downloadandZip(downloadurl, headers, name)
                    return os.getcwd() + "\msedgedriver.exe"
                else:
                    print("正在退出")
                    return False


if __name__ == "__main__":
    headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3861.400 QQBrowser/10.7.4313.400'}
    print("欢迎使用UML网课刷取系统\n")
    path1 = getEdgePath()
    path2 = path1.replace("\\", "//").replace("\"", "")
    oldversion = getversion(path2)
    downloadurl="https://msedgedriver.azureedge.net/"+oldversion+"/edgedriver_win64.zip"
    driverfilepath = startDownloadandZipexc(downloadurl, headers)
    if driverfilepath!=False:
        print("浏览器驱动器路径为:"+driverfilepath+"不必要,请勿删除")
        inithtml = "http://passport2.chaoxing.com/login?fid=&refer="
        isHeadless = isHeadless()
        Driver = init(driverfilepath, isHeadless)
        stat1=time.time()
        login(Driver, inithtml)
        end1=time.time()
        if(end1-stat1<15):
            listinfo = getTopicInfo()
            getfirstpage(Driver, listinfo)
        else:
            print("二维码已失效,请重启系统")

写脚本的一些知识点

下面就是总结环节,正所谓,没有总结就没有进步,所以再忙也要去总结升华

关于部分网页无法找到元素的问题1

问题描述

这个问题我想,大概还是基础知识不牢靠的原因

selenium中的寻找元素,只是能寻找到当前页面的一个html中的元素,如果出现嵌套的网页就无法寻找到所嵌套网站中的元素的!!对我说的就是iframe!!!这个自带黑魔法的东西

上图: 

出现这种情况是找不到的!

解决方案

太难了,哈哈,我捣鼓了两天里

方案1

我们需要先获取iframe中的src也就是嵌套网页的地址,然后再去请求就好了

    # 寻找第一层框架入口
    s = Driver.find_element(By.ID, "frame_content").get_attribute("src")
    # 进入第一层框架入口
    Driver.get(s)

方案2

当然我们页可以直接去对iframe执行点击操作,这样更快,更人性化

关于部分网页无法找到元素的问题2

问题描述

这种情况是出现打开新的网页的情况,当我们打开了新的页面时,但是我们WebDriver并不会自动跳转的!他还在原来的页面时,所以我们去寻找新页面中的元素就会找不到了!!

如图所示

解决方案

那怎么样让驱动也去跳转那?

那我们需要获取句柄了(我只会windows平台上的)

注意这是我们获取的时当前驱动的所有句柄,如果有两个页面的话就会有两个句柄的,于是我们取出最后也个句柄,并使用switch_to.window方法使我们的浏览器驱动跳转到我们需要的(及第二个)页面。

    # 获取当前句柄,这很重要!!
    url = Driver.window_handles
    # 跳转到我们需要的网页
    Driver.switch_to.window(url[1])

被网站检查出来我们使用了selenium了怎么办?

问题描述

现在自动化工具越来越火了,一些厂商就针对与自动化工具做了限制,如:如果加了无头模式

一些网站的js就会检测出来,使我们的操作失效

解决方法

直接看代码吧,这玩意不好解释


    # 创建option对象
    options = Options()
    # 设置无头模式即浏览器不弹出,只在后台运行
    options.add_argument("headless")
    # 解决部分网站的对于Selenium的js监测机制,
    # 以下2行
    options.add_experimental_option('excludeSwitches', ['enable-automation'])
    options.add_experimental_option('useAutomationExtension', False)
    # 加载浏览器驱动
    Webdriver = Service(driverfilename)
    # 加载驱动和无头
    driver = webdriver.Edge(service=Webdriver, options=options)
    # 解决部分网站的对于Selenium的js监测机制,
    # 以下1行
    driver.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument",
                           {'source': 'Object.defineProperty(navigator,"webdriver",{get:()=>undefind})'})

如何实现前进后退

前进及不用说了,直接请求即可了,但是怎么去实现后退那?

上代码,这么少?哈哈其实坑多着哩!这个后退只能实现一个,也就是说如果连续写多个back()就会失效的!所以说该用driver.current_url去获取网址时就多用,不要去懒省事的

                # 回到上一个页面
                Driver.back()
driver.current_url

当使用py删除文件时报禁止访问怎么办

不要慌不要慌,这种情况多出现在删除文件夹时这时我们就需要去使用shutil这个模块了,它可以保保证删除文件夹时不出错,但是用它去删除文件时却会出错的,要牢记

import shutil
if os.path.exists(name1):
    shutil.rmtree(name1)
if os.path.exists(name):
    os.remove(name)

怎么使用py实现解压文件?

我们使用zipfile模块,去实现首先打开文件 使用extratall()就可以实现解压了

注意:解压完成是会自动删除源文件的

import zipfile
# 文件解压
with zipfile.ZipFile(name) as zf:
    zf.extractall()

怎么打开系统的图片应用向用户展示图片?

注意这里好像只支持win系统

代码

def showimg(path):
    userPlatform = platform.system()  # 获取操作系统
    if userPlatform == 'Windows':  # Mac
        os.startfile(path)
    else:
        print("暂且不支持您的操作系统")

效果展示

怎么去下载网络资源?

下载网络资源

        dow = requests.get(downloadurl, headers)
        open("drive.zip", "wb").write(dow.content)

下载网页

使用的是py自带的标准库,不需要去下载第3方库

urllib.request.urlretrieve("URL路径","保存路径")

怎么获取当前路径?

 一句

os.getcwd()

怎么使用Webderive截图?

 Driver.save_screenshot(path)

JSON数据的天坑?

当我们去使用xhr,窃取响应时,通常会使用post请求,但是请注意,这里post 请求中的参数

1 必须是双引号

2 就算是数字也必须加上引号

3 没有值的话就加空字符串

4 布尔值必须是小写的true/false

请注意第2条,如果不加引号,js会把它按照int32类型处理但是当创出int32的范围时就会请求失败,这就是为什么int类型的数据也要加引号的 原因

1、传统表单post请求(xhr的请求)

import requests
url = "https://tests"
data = {"key":"value"}
res = requests.post(url=url,data=data)
print(res.text)

2、json类型的post请求
import requests
url = "https://tests"
data = '{"key":"value"}'
#字符串格式
res = requests.post(url=url,data=data)
print(res.text)

最后的一些未解决的问题

我们使用selenium获取到的cooike不全怎么办?

怎么根据快捷方式找到源文件的位置?

恳请大佬们解答

物联沃分享整理
物联沃-IOTWORD物联网 » 记一次失败的使用python selenium刷课学习通脚本(细节满满)+关于使用selenium的疑难杂症解决+json数据请求的疑难杂症+py冷门知识

发表评论