二人同行 發表於 2019-12-12 14:35:00

《手把手教你》系列进阶篇之2-python+ selenium自动化测试 - python基础扫盲(详细教程)

<h3>1. 简介</h3>
<p>  这篇文章主要是分享讲解一下,如何封装自己用到的方法和类。以便方便自己和别人的调用,这样就可以避免重复地再造轮子。</p>
<p>  封装(Encapsulation)是面向对象的三大特征之一(另外两个是继承和多态),它指的是将对象的状态信息隐藏在对象内部,不允许外部程序直接访问对象内部信息,而是通过该类所提供的方法来实现对内部信息的操作和访问。</p>
<p>就好比使用计算机,我们只需要使用计算机提供的键盘,就可以达到操作计算机的目的,至于在敲击键盘时计算机内部是如何工作,我们根本不需要知道。</p>
<p>封装机制保证了类内部数据结构的完整性,因为使用类的用户无法直接看到类中的数据结构,只能使用类允许公开的数据,很好地避免了外部对内部数据的影响,提高了程序的可维护性。总的来说,对一个类或对象实现良好的封装,可以达到以下目的:</p>
<ul>
<li>
<p>隐藏类的实现细节。</p>
</li>
<li>
<p>让使用者只能通过事先预定的方法来访问数据,从而可以在该方法里加入控制逻辑,限制对属性的不合理访问。</p>
</li>
<li>
<p>可进行数据检查,从而有利于保证对象信息的完整性。</p>
</li>
<li>
<p>便于修改,提高代码的可维护性。</p>
</li>


</ul>
<p>为了实现良好的封装,需要从以下两个方面来考虑:</p>
<ol>
<li>
<p>将对象的属性和实现细节隐藏起来,不允许外部直接访问。</p>
</li>
<li>
<p>把方法暴露出来,让方法来控制对这些属性进行安全的访问和操作。</p>
</li>


</ol>
<p>因此,实际上封装有两个方面的含义:把该隐藏的隐藏起来,把该暴露的暴露出来。&nbsp;</p>
<h3 class="title-article">2. 二次封装Selenium中几个方法</h3>
<p>  本文来介绍,如何把常用的几个webdriver的方法封装到自己写的一个类中去,这个封装过程叫二次封装Selenium方法。我们把打开站点,浏览器前进和后退,关闭和退出浏览器这这个方法封装到一个新写的类中去。</p>
<p>我们按照如下层次结构在PyCharm中新建两个包和两个.py文件:</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191212085659430-1620937194.png" alt=""></p>
<p>&nbsp; &nbsp; &nbsp; 上图,baidu_search.py是我们编写测试脚本的python文件,具体测试代码写在这个文件。包test1下的basepage.py文件是这次我们介绍的二次封装selenium方法而新建的。这里提一下,python中默认规则,包名和文件名都是小写,类名称单词首字母大写,函数名称小写,多个字母下划线隔开。我们尽量遵守下这个不成文的约定。</p>
<p>来看看basepage.py的内容:</p>
<h4>2.1 代码实现:</h4>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191212102853043-578232545.png" alt=""></p>
<h4>2.2 参考代码:</h4>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> coding=utf-8🔥</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 2.注释:包括记录创建时间,创建人,项目名称。</span>
<span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">
Created on 2019-12-12
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之2-python+ selenium自动化测试 - python基础扫盲
</span><span style="color: rgba(128, 0, 0, 1)">'''</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 3.导入模块</span>

<span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BasePage(object):
    </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
    主要是把常用的几个Selenium方法封装到BasePage这个类,我们这里演示以下几个方法
    back()
    forward()
    get()
    quit()
    </span><span style="color: rgba(128, 0, 0, 1)">"""</span>
    <span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self, driver):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
      写一个构造函数,有一个参数driver
      :param driver:
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
      self.driver </span>=<span style="color: rgba(0, 0, 0, 1)"> driver

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> back(self):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
      浏览器后退按钮
      :param none:
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
      self.driver.back()

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> forward(self):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
      浏览器前进按钮
      :param none:
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
      self.driver.forward()

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> open_url(self, url):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
      打开url站点
      :param url:
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
      self.driver.get(url)

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> quit_browser(self):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
      关闭并停止浏览器服务
      :param none:
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(0, 0, 0, 1)">
      self.driver.quit()</span></pre>
</div>
<p>上面的''''''是文档注释,一般在类的开始和函数的开始,用两个''''''括起来,简单描述下这个类或者函数的功能。</p>
<h3>3.&nbsp;调用自己封装过的方法</h3>
<p>接下来看看,我们脚本文件中如何去调用我们自己封装过的方法。</p>
<p>baidu_search.py的内容如下:</p>
<h4>3.1 代码实现:</h4>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191212104748556-925099244.png" alt=""></p>
<h4>3.2 参考代码:</h4>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> coding=utf-8🔥</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 2.注释:包括记录创建时间,创建人,项目名称。</span>
<span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">
Created on 2019-12-12
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之2-python+ selenium自动化测试 - python基础扫盲
</span><span style="color: rgba(128, 0, 0, 1)">'''</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 3.导入模块</span>
<span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> time
</span><span style="color: rgba(0, 0, 255, 1)">from</span> selenium <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> webdriver
</span><span style="color: rgba(0, 0, 255, 1)">from</span> blog.basepage <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> BasePage


</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BaiduSearch(object):

    driver </span>=<span style="color: rgba(0, 0, 0, 1)"> webdriver.Chrome()
    driver.maximize_window()
    driver.implicitly_wait(</span>10<span style="color: rgba(0, 0, 0, 1)">)
   
    basepage </span>=<span style="color: rgba(0, 0, 0, 1)"> BasePage(driver)
   
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> open_baidu(self):
      self.basepage.open_url(</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">https://www.baidu.com</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
      time.sleep(</span>1<span style="color: rgba(0, 0, 0, 1)">)
   
    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> test_search(self):
      self.driver.find_element_by_id(</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">kw</span><span style="color: rgba(128, 0, 0, 1)">'</span>).send_keys(<span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">Selenium</span><span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(0, 0, 0, 1)">)
      time.sleep(</span>1<span style="color: rgba(0, 0, 0, 1)">)
      self.basepage.back()
      self.basepage.forward()
      self.basepage.quit_browser()

baidu </span>=<span style="color: rgba(0, 0, 0, 1)"> BaiduSearch()
baidu.open_baidu()
baidu.test_search()</span></pre>
</div>
<h4>3.3 运行结果:</h4>
<p>运行代码后,控制台打印如下图的结果</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191212104557256-1270842674.png" alt=""></p>
<p>&nbsp; &nbsp; &nbsp; 上面self.basepage的几行代码就是调用我们自己封装的方法去执行相关webdriver操作。这个只是一个简单的封装介绍,等后面,我们介绍了字符串切割,我们会再次介绍二次封装Selenium方法,例如将会把八大find_element方法封装到一个方法里去。</p>
<h3 class="title-article">4. 封装一个自己的类-浏览器引擎类</h3>
<p>  通过上边的一小节我们知道了,如何去封装几个简单的Selenium方法到我们自定义的类,所以我们趁热打铁:这次我们编写一个类,叫浏览器引擎类,通过更改一个字符串的值,利用if语句去判断和控制启动那个浏览器。这里我们暂时,支持三大浏览器</p>
<p>(IE,Chrome,Firefox)。这里有一个前提条件,在基础篇中,启动三大浏览器的driver文件,检查下你的Python安装路径下有没有这三个driver插件,如果没有,请回到基础篇的如何启动火狐和IE浏览器文章去看看如何做。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 我们继续在test1这个包下新建一个browser_engine.py文件,然后在另外一个包下新建一个test.py文件去测试这个浏览器引擎类是否工作正常。这个浏览器引擎类,我们一开始写简单一点,只写启动浏览器。</p>
<p>先看看browser_engine.py中的代码:</p>
<h4>4.1 代码实现:</h4>
<h5><strong>4.1.1 browser_engine.py</strong></h5>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191212105917615-1811927608.png" alt=""></p>
<h5><strong>4.1.2 test.py</strong></h5>
<p><strong><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191212110121542-1233075946.png" alt=""></strong></p>
<h4>4.2 参考代码:</h4>
<h5><strong>4.2.1 browser_engine.py</strong></h5>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> coding=utf-8🔥</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 2.注释:包括记录创建时间,创建人,项目名称。</span>
<span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">
Created on 2019-12-12
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之2-python+ selenium自动化测试 - python基础扫盲
</span><span style="color: rgba(128, 0, 0, 1)">'''</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 3.导入模块</span>

<span style="color: rgba(0, 0, 255, 1)">from</span> selenium <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> webdriver


</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> BrowserEngine(object):
    </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
    定义一个浏览器引擎类,根据browser_type的值去,控制启动不同的浏览器,这里主要是IE,Firefox, Chrome
    </span><span style="color: rgba(128, 0, 0, 1)">"""</span>
    <span style="color: rgba(0, 0, 255, 1)">def</span> <span style="color: rgba(128, 0, 128, 1)">__init__</span><span style="color: rgba(0, 0, 0, 1)">(self, driver):
      self.driver </span>=<span style="color: rgba(0, 0, 0, 1)"> driver

    browser_type </span>= <span style="color: rgba(128, 0, 0, 1)">"</span><span style="color: rgba(128, 0, 0, 1)">IE</span><span style="color: rgba(128, 0, 0, 1)">"</span> <span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> maybe Firefox, Chrome, IE</span>

    <span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> get_browser(self):
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span><span style="color: rgba(128, 0, 0, 1)">
      通过if语句,来控制初始化不同浏览器的启动,默认是启动Chrome
      :return: driver
      </span><span style="color: rgba(128, 0, 0, 1)">"""</span>

      <span style="color: rgba(0, 0, 255, 1)">if</span> self.browser_type == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Firefox</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
            driver </span>=<span style="color: rgba(0, 0, 0, 1)"> webdriver.Firefox()
      </span><span style="color: rgba(0, 0, 255, 1)">elif</span> self.browser_type == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">Chrome</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
            driver </span>=<span style="color: rgba(0, 0, 0, 1)"> webdriver.Chrome()
      </span><span style="color: rgba(0, 0, 255, 1)">elif</span> self.browser_type == <span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(128, 0, 0, 1)">IE</span><span style="color: rgba(128, 0, 0, 1)">'</span><span style="color: rgba(0, 0, 0, 1)">:
            driver </span>=<span style="color: rgba(0, 0, 0, 1)"> webdriver.Ie()
      </span><span style="color: rgba(0, 0, 255, 1)">else</span>: driver =<span style="color: rgba(0, 0, 0, 1)"> webdriver.Chrome()

      driver.maximize_window()
      driver.implicitly_wait(</span>10<span style="color: rgba(0, 0, 0, 1)">)

      </span><span style="color: rgba(0, 0, 255, 1)">return</span> driver</pre>
</div>
<h5><strong>4.2.2 test.py</strong></h5>
<p>再看看test.py代码,进行测试,更改browser_engine.py中browser_type的值,去测试三大浏览器是否启动正常。</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> coding=utf-8🔥</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 1.先设置编码,utf-8可支持中英文,如上,一般放在第一行</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 2.注释:包括记录创建时间,创建人,项目名称。</span>
<span style="color: rgba(128, 0, 0, 1)">'''</span><span style="color: rgba(128, 0, 0, 1)">
Created on 2019-12-12
@author: 北京-宏哥   QQ交流群:705269076
Project: 《手把手教你》系列进阶篇之2-python+ selenium自动化测试 - python基础扫盲
</span><span style="color: rgba(128, 0, 0, 1)">'''</span>

<span style="color: rgba(0, 128, 0, 1)">#</span><span style="color: rgba(0, 128, 0, 1)"> 3.导入模块</span>
<span style="color: rgba(0, 0, 255, 1)">from</span> test1.browser_engine <span style="color: rgba(0, 0, 255, 1)">import</span><span style="color: rgba(0, 0, 0, 1)"> BrowserEngine


</span><span style="color: rgba(0, 0, 255, 1)">class</span><span style="color: rgba(0, 0, 0, 1)"> TestBrowserEngine(object):

    </span><span style="color: rgba(0, 0, 255, 1)">def</span><span style="color: rgba(0, 0, 0, 1)"> open_browser(self):
      browserengine </span>=<span style="color: rgba(0, 0, 0, 1)"> BrowserEngine(self)
      driver </span>=<span style="color: rgba(0, 0, 0, 1)"> browserengine.get_browser()

tbe </span>=<span style="color: rgba(0, 0, 0, 1)"> TestBrowserEngine()
tbe.open_browser()</span></pre>
</div>
<h4>4.3 运行结果:</h4>
<p>再看看test.py代码,进行测试,更改browser_engine.py中browser_type的值,去测试三大浏览器是否启动正常。</p>
<p>运行代码后,控制台打印如下图的结果</p>
<p><img src="https://img2018.cnblogs.com/i-beta/1232840/201912/1232840-20191212104557256-1270842674.png" alt=""></p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 目前,自定义的浏览器引擎类到这里就封装好了,只支持打开不同浏览器,需要手动修改,引擎类中browser_type的值。看起来功能简单,但是我们只是需要学习这种做事的方式和思维,在下一个部分,框架设计的时候,我会再告诉大家如何去加强这个引擎类</p>
<p>的功能,到时候去修改配置文件中的浏览器类型,而不是修改代码中的字段。通过修改配置文件,从而去打开不同浏览器,并开始测试相关脚本。</p>
<h3>5. 小结</h3>
<p>  好了,今天的分享就到这里吧!!!谢谢各位的耐心阅读。</p>
<p>&nbsp;</p>
<p style="text-align: center"><span style="font-size: 18px"><strong><strong>您的肯定就是我进步的动力。</strong>如果你感觉还不错,就请鼓励一下吧!记得随手点波&nbsp;<span style="font-size: 18pt; color: rgba(255, 0, 0, 1)">推荐</span>&nbsp;不要忘记哦!!!</strong></span></p>
<p>&nbsp;</p>
<p><img style="display: block; margin-left: auto; margin-right: auto" src="https://img2018.cnblogs.com/blog/1232840/201908/1232840-20190816135641371-1314831001.gif" alt=""></p>

</div>
<div id="MySignature" role="contentinfo">
    <div id="MySignature" style="display: block">
        <div style="font-size: 13px; border: 1px dashed rgb(45, 161, 45); padding: 10px 15px; background-color: rgb(248, 248, 248)">
                <label style="font-weight: bold">
                        &nbsp;&nbsp;&nbsp;&nbsp;为了方便大家在移动端也能看到我分享的博文,现已注册个人微信公众号,扫描左下方二维码即可,欢迎大家关注,提前解锁更多测试干货!有时间会及时分享相关技术博文。
                </label>
                <br>
                <label style="font-weight: bold">
                        &nbsp;&nbsp;&nbsp;&nbsp;为了方便大家互动讨论相关技术问题,刚刚建立了咱们的专门的微信群交流互动群,群内会分享交流测试领域前沿知识。请您扫描中间的微信二维码进群
                </label>
                <br>
                <label style="font-weight: bold">
                        &nbsp;&nbsp;&nbsp;&nbsp;为了方便大家互动讨论相关技术问题,现已组建专门的微信群,由于微信群满100,请您扫描右下方宏哥个人微信二维码拉你进群
                        <label style="font-weight: bold; color: red; font-size: 15px">
                                (请务必备注:已关注公众号进群)平时上班忙(和你一样),所以加好友不及时,请稍安勿躁~
                        </label>
                        ,欢迎大家加入这个大家庭,我们一起畅游知识的海洋。
                </label>
                <br>
                &nbsp;&nbsp;&nbsp;&nbsp;感谢您花时间阅读此篇文章,如果您觉得这篇文章你学到了东西也是为了犒劳下博主的码字不易不妨打赏一下吧,让博主能喝上一杯咖啡,在此谢过了!
                <br>
                &nbsp;&nbsp;&nbsp;&nbsp;如果您觉得阅读本文对您有帮助,请点一下左下角
               
                        “推荐”
               
                按钮,您的
                <label style="font-weight: bold; color: red; font-size: 15px">
                        “推荐”
                </label>
                将是我最大的写作动力!另外您也可以选择
               
                        【
                        <strong>
                                关注我
                        </strong>
                        】
               
                ,可以很方便找到我!
                <br>
                &nbsp;&nbsp;&nbsp;&nbsp;本文版权归作者和博客园共有,来源网址:
               
                        https://www.cnblogs.com/du-hong
               
                欢迎各位转载,但是未经作者本人同意,转载文章之后必须在文章页面明显位置给出作者和原文连接,否则保留追究法律责任的权利!
        </div>
        <div style="text-align: center; margin-top: 10px">
                <p style=" font-weight: bolder; color: red; ">
                        公众号(关注宏哥)&NonBreakingSpace; &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;
                        &NonBreakingSpace; &NonBreakingSpace; &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;
                        &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace; &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;
                        &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace; &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;
                        微信群(扫码进群) &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;
                        &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace; &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;
                        &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace; &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;
                        &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace;
                        &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace; &NonBreakingSpace;&NonBreakingSpace;
                        &NonBreakingSpace;&NonBreakingSpace;&NonBreakingSpace; &NonBreakingSpace;&NonBreakingSpace;客服微信
                </p>
                <img style="width: 200px;padding-right: 50px;" alt="个人微信公众号" src="https://img2018.cnblogs.com/common/1741949/201911/1741949-20191119095948011-608816619.png">
                <img style="width: 200px;padding-right: 65px;" alt="微信群" src="https://img2024.cnblogs.com/blog/1232840/202506/1232840-20250610113707419-637869921.png">
                <img style="width: 200px" alt="个人微信" src="https://img2018.cnblogs.com/common/1741949/201911/1741949-20191106101257091-849954564.png">
        </div>
</div><br><br>
来源:https://www.cnblogs.com/du-hong/p/12023115.html
頁: [1]
查看完整版本: 《手把手教你》系列进阶篇之2-python+ selenium自动化测试 - python基础扫盲(详细教程)