爬虫(10)selenium上 模拟登录豆瓣案例

1. 驱动安装

selenium介绍:selenium是一个web的自动化测试工具,最初是为网站自动化测试而开发的,selenium可以直接运行在浏览器上,它支持所有主流的浏览器,可以接收指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏。需要配合浏览器驱动使用。chromedriver是一个驱动Chrome浏览器的驱动程序,使用他才可以驱动浏览器。当然针对不同的浏览器有不同的driver。以下列出了不同浏览器及其对应的driver:

  • Chrome:https://sites.google.com/a/chromium.org/chromedriver/downloads
  • Firefox:https://github.com/mozilla/geckodriver/releases
  • Edge:https://developer.microsoft.com/en-us/microsoft-edge/tools/webdriver/
  • Safari:https://webkit.org/blog/6900/webdriver-support-in-safari-10/
  • 下载chromedriver
  • 百度搜索:淘宝镜像(https://npm.taobao.org/)
  • 安装总结:https://www.jianshu.com/p/a383e8970135
  • 安装Selenium:pip install selenium 也可以换源安装:
    pip install -i https://pypi.tuna.tsinghua.edu.cn/simple selenium
    这个是清华的源,也可以用别的源。

1.1 Phantomjs快速入门

无头浏览器:一个完整的浏览器内核,包括js解析引擎,渲染引擎,请求处理等,但是没有显示和用户交互的界面。
我们需要下载Phantoumjs驱动,解压缩后,把驱动exe文件放到python的根目录文件夹里面,因为这个文件夹已经添加到环境变量里了。
案例:打开百度。

from selenium import webdriver
driver = webdriver.PhantomJS()
driver.get('https://www.baidu.com/')

显示结果

D:\Python38\python.exe D:/work/爬虫/Day10/my_code/Phantojs_getin.py
D:\Python38\lib\site-packages\selenium\webdriver\phantomjs\webdriver.py:49: UserWarning: Selenium support for PhantomJS has been deprecated, please use headless versions of Chrome or Firefox instead
  warnings.warn('Selenium support for PhantomJS has been deprecated, please use headless '

Process finished with exit code 0

其实,百度网页已经被打开过了,只是你没有看见,因为Phantomjs没有显示功能。但有一个截屏功能。我们演示一下。

from selenium import webdriver
driver = webdriver.PhantomJS()
driver.get('https://www.baidu.com/')
driver.save_screenshot('baidu.png')

在我的目录里就多了一个“baidu.png”的文件。
在这里插入图片描述
点开可以看到截屏
在这里插入图片描述
一个没有登录过的界面。
下面我们操作一下输入框,那么我们先要找到输入框的位置。通过定位的方式,直接在百度界面右键》检查》元素定位符,定位一下输入框,就可以得到位置。我们可以通过id="kw"标签来定位它。
代码:

from selenium import webdriver
driver = webdriver.PhantomJS()
driver.get('https://www.baidu.com/')
# 操作输入框,先定位输入框
driver.find_element_by_id('kw').send_keys('python')
# 截屏
driver.save_screenshot('baidu_1.png')

在这里插入图片描述
如果我们要搜索,我们要加入点击。我们通过id="su"标签来查找,代码:

from selenium import webdriver
driver = webdriver.PhantomJS()
driver.get('https://www.baidu.com/')
# 操作输入框,先定位输入框
driver.find_element_by_id('kw').send_keys('python')
# 点击事件
button_tag = driver.find_element_by_id('su')
button_tag.click()
# 查看当前请求的url地址
print(driver.current_url)
# 截屏
driver.save_screenshot('baidu_2.png')

结果

https://www.baidu.com/s?ie=utf-8&f=8&rsv_bp=1&rsv_idx=1&tn=baidu&wd=python&fenlei=256&rsv_pq=97a4e5570000d3f9&rsv_t=f318U3sVVCvcZeSx6xhJZiX2%2B5LU7NW2CMwM1gQfD08RPAjfrW3%2F6VUwDzI&rqlang=cn&rsv_enter=0&rsv_dl=ib&rsv_sug3=6&rsv_btype=i&inputT=136&rsv_sug4=136

这是我们刚才搜索百度内容的url地址。
Phantomjs我们就了解这么多。

2. Chromedriver快速入门

同样的,我们可以在淘宝镜像里下载Chromedriver,解压缩以后,我们可以把exe文件放到python的根目录下。然后我们就可以调用了,写代码试试:

from selenium import webdriver
import time
driver = webdriver.Chrome() # 记得这里Chrome首字母是大写,否则会报错。
# 打开百度网页
driver.get('https://baidu.com/')
# 十五秒后进行下一步操作
time.sleep(15)
# 退出网页
driver.quit()

运行后,百度网页被打开,15秒后自动关闭。就是这个效果。quit()方法是退出浏览器,即关闭所有窗口。close()方法是关闭当前窗口。driver.maximize_window()可以实现窗口最大化。如果我们还想学习更多的方法,我们可以Ctrl+Alt点击打开webdriver了解更多的方法。

3. 定位元素

类似Phantomjs我们直接看代码,以下的代码时定位到输入框,3秒后输入python,2秒后点击搜索,5秒后关闭。

from selenium import webdriver
import time
driver = webdriver.Chrome() # 记得这里Chrome首字母是大写,否则会报错。
# 打开百度网页
driver.get('https://baidu.com/')
time.sleep(3)
driver.find_element_by_id('kw').send_keys('python')
button_tag = driver.find_element_by_id('su')
time.sleep(2)
button_tag.click()
time.sleep(5)
driver.quit()

3.1 另一种定位方式

还有另一种定位方式,看代码:

from selenium import webdriver
from selenium.webdriver.common.by import By   # 看这里,driver.后面选find_element(),
# 括号里输入By,然后.后面可以跟很多中查找定位方法
import time
driver = webdriver.Chrome() # 记得这里Chrome首字母是大写,否则会报错。
# 打开百度网页
driver.get('https://baidu.com/')
time.sleep(3)
# driver.find_element_by_id('kw').send_keys('python')
driver.find_element(By.ID,'kw').send_keys('miantaoge') # .find_element(By.)后面会提示很多中定位方法,
# 然后自由选择,这里我们仍然选择id定位,后面就逗号,然后输入id值。效果是跟刚才一样的。
button_tag = driver.find_element_by_id('su')
time.sleep(2)
button_tag.click()
time.sleep(5)
driver.quit()

3.2 通过class_name定位

这次我们用属性名定位百度输入框
在这里插入图片描述
我们用class = "s_ipt"进行定位,代码:

from selenium import webdriver
from selenium.webdriver.common.by import By   # 看这里,driver.后面选find_element(),
# 括号里输入By,然后.后面可以跟很多中查找定位方法
import time
driver = webdriver.Chrome() # 记得这里Chrome首字母是大写,否则会报错。
# 打开百度网页
driver.get('https://baidu.com/')
time.sleep(3)
# driver.find_element_by_id('kw').send_keys('python')
# driver.find_element(By.ID,'kw').send_keys('miantaoge') # .find_element(By.)后面会提示很多中定位方法,
# 然后自由选择,这里我们仍然选择id定位,后面就逗号,然后输入id值。效果是跟刚才一样的。
driver.find_element_by_class_name('s_ipt').send_keys('石家庄疫情')
# driver.find_element(By.CLASS_NAME,'s_ipt').send_keys('石家庄疫情')   用这个方法也是一样的
button_tag = driver.find_element_by_id('su')
time.sleep(2)
button_tag.click()
time.sleep(5)
driver.quit()

运行后效果是一样的。

3.3 通过name定位

重复的代码不再写了,只写关键句:

driver.find_element_by_name('wd').send_keys('乌鲁木齐疫情')
driver.find_element(By.NAME,'wd').send_keys('北京疫情')

运行后效果是一样的。

3.4 通过tag_name进行定位

最好不用这种方式定位,可以用这种方式找一批标签是可以的,因为同名标签太多,定位不准确。

3.5 通过xpath进行定位

在找不到以上标签的的情况下,可以尝试用xpath定位,要写语句。

driver.find_element_by_xpath('//input[@id="kw"]').send_keys('哈尔滨疫情')

补充代码后可以运行得到相同的效果。如果直接用tag_name,input去定位肯定报错,因为叫input的标签很多。如果打印,返回的是列表对象。

3.6 通过css选择器定位

这需要会一些css语法。

driver.find_element_by_css_selector('.s_ipt').send_keys('长春疫情')

这是通过class_name来定位的。
另外可以driver.find_elements_by_css_selector()查找的是一批符合要求的标签。

4. 操作表单元素&select标签

下面我们做以下操作,我们在输入框输入“无痕的雨”,然后点击“搜索”,然后再清空一下,最后关闭。

from selenium import webdriver
import time
driver = webdriver.Chrome()
# 在百度输入框内输入“无痕的雨“
driver.get('https://www.baidu.com/')
time.sleep(3)
driver.find_element_by_id('kw').send_keys('无痕的雨')
time.sleep(3)
# 点击搜索
button_tag = driver.find_element_by_id('su')
button_tag.click()
time.sleep(3)
# 清除输入内容
driver.find_element_by_id('kw').clear()
time.sleep(3)
driver.close()

结果正如我们所描述的那样呈现了。
下面我们看一个示例网站:示例网站
这个网站里面有下拉菜单,我们的目的是选择其中的一个菜单选项,比如第一个"try me!"输入框里选择“Japan”。这就用到了select标签的操作知识。
我们右键输入框,选择检查,打开代码页面,我们看到了一个class="nojs"的标签。
在这里插入图片描述
双击这个标签就会出现一系列的value值,这些就是我们要的选项,其中第四个就是JP我们要的对象。select元素是不能直接点击的,因为点击后还需要选中元素。这时候,selenium就为我们提供了一个类:from selenium.webdriver.support.ui import Select 。将获取到的元素当成参数传入到这个类中,创建这个对象,以后就可以使用这个对象进行选择了。我们在代码中看:

from selenium import webdriver
import time
driver = webdriver.Chrome()
# 打开示例网页
driver.get('https://www.17sucai.com/pins/demo-show?id=5926')
time.sleep(3)
# 定位select标签
select_tag = driver.find_element_by_class_name('nojs')
# 操作select
# 1 根据value值来选择
select_tag.select_by_value('JP') # 先来一个错误的示范,这样直接写是会报错的
'''
selenium.common.exceptions.NoSuchElementException: Message: no such element: Unable to locate element: {"method":"css selector","selector":".nojs"}
  (Session info: chrome=88.0.4324.104)
报错说没有找到这个元素,不能定位元素"nojs"
'''

我们查找一下网页代码,往上查找可以看到一个iframe标签。
在这里插入图片描述
iframe是一个html标签,作用是文档中的文档,或者浮动的框架(frame)。iframe标签会创建包含另外一个文档的内联框架(即行内框架)。
标签内有个src = ‘https://www.17sucai.com/preview/157524/2014-07-08/jQuery自定义下拉菜单插件dropkick/index.html’,点击它,就会出现一模一样的另一个页面。
在这里插入图片描述
说明在这个页面里嵌套了一个一模一样的页面。如果我们要选中select标签的话,要将我们的selenium切换到这个页面。那么我们就需要切换iframe,

driver.switch_to_frame()

这是过时的方法,但是还能用。然后将查到的iframe元素当成参数传递进去。

from selenium import webdriver
import time
driver = webdriver.Chrome()
# 打开示例网页
driver.get('https://www.17sucai.com/pins/demo-show?id=5926')
time.sleep(3)
# 切换iframe
driver.switch_to_frame(driver.find_element_by_id('iframe')) # 将定位到的iframe标签元素当成参数传递进去
# 定位select标签
select_tag = driver.find_element_by_class_name('nojs')
# 操作select
# 1 根据value值来选择
select_tag.select_by_value('JP') # 这时仍然会报错
'''
AttributeError: 'WebElement' object has no attribute 'select_by_value'
报错说'WebElement'对象没有'select_by_value'这个方法。
'''

这是因为我们没有导入卡面提到的Select类,现在我们导入一下。仔细看代码中的注释:

from selenium import webdriver
import time
from selenium.webdriver.support.ui import Select  # 导入Select类
driver = webdriver.Chrome()
# 打开示例网页
driver.get('https://www.17sucai.com/pins/demo-show?id=5926')
time.sleep(3)
# 切换iframe
driver.switch_to_frame(driver.find_element_by_id('iframe')) # 将定位到的iframe标签元素当成参数传递进去
# 定位select标签
# select_tag = driver.find_element_by_class_name('nojs')
select_tag = Select(driver.find_element_by_class_name('nojs')) # 将之前定位到的'nojs'标签当作参数传递进去
# 操作select
# 1 根据value值来选择
# select_tag.select_by_value('JP')
select_tag.select_by_value('JP')  # 这时在.的时候就有提示select_by_value()了,不过仍然出现了方法过时提示
'''
 DeprecationWarning: use driver.switch_to.frame instead
  driver.switch_to_frame(driver.find_element_by_id('iframe')) 
  提示可以用driver.switch_to.frame 代替 driver.switch_to_frame
'''

这时,运行后就出现了Japan选项了。
在这里插入图片描述
不过仍然出现了方法过时提示:DeprecationWarning: use driver.switch_to.frame instead
driver.switch_to_frame(driver.find_element_by_id(‘iframe’)) ( 提示可以用driver.switch_to.frame 代替 driver.switch_to_frame)。我们可以试一下:

from selenium import webdriver
import time
from selenium.webdriver.support.ui import Select  # 导入Select类
driver = webdriver.Chrome()
# 打开示例网页
driver.get('https://www.17sucai.com/pins/demo-show?id=5926')
time.sleep(3)
# 切换iframe
# driver.switch_to_frame(driver.find_element_by_id('iframe')) # 将定位到的iframe标签元素当成参数传递进去
driver.switch_to.frame(driver.find_element_by_id('iframe')) # 将driver.switch_to_frame换成driver.switch_to
# 定位select标签
# select_tag = driver.find_element_by_class_name('nojs')
select_tag = Select(driver.find_element_by_class_name('nojs')) # 将之前定位到的'nojs'标签当作参数传递进去
# 操作select
# 1 根据value值来选择
# select_tag.select_by_value('JP')
select_tag.select_by_value('JP')  # 这时没有报错了。


上面我们是用value标签来定位的,第二种操作方式,还可以通过下标索引值来定位:

from selenium import webdriver
import time
from selenium.webdriver.support.ui import Select  # 导入Select类
driver = webdriver.Chrome()
# 打开示例网页
driver.get('https://www.17sucai.com/pins/demo-show?id=5926')
time.sleep(3)
# 切换iframe
# driver.switch_to_frame(driver.find_element_by_id('iframe')) # 将定位到的iframe标签元素当成参数传递进去
driver.switch_to.frame(driver.find_element_by_id('iframe')) # 将driver.switch_to_frame换成driver.switch_to
# 定位select标签
# select_tag = driver.find_element_by_class_name('nojs')
select_tag = Select(driver.find_element_by_class_name('nojs')) # 将之前定位到的'nojs'标签当作参数传递进去
# 操作select
# 1 根据value值来选择
# select_tag.select_by_value('JP')
select_tag.select_by_value('JP')
# 2 根据下标索引来定位
select_tag.select_by_index(4)


在这里插入图片描述
我们看到出现了我们想要的结果。

5. 操作非select标签

我们手动打开上述示例网页的第二个框,我们看到这个跟第一个有点区别,这个不是select标签了。
在这里插入图片描述
但也同样在iframe标签之下,仍然需要用到切换到iframe。 我们先用Select试一下:

from selenium import webdriver
import time
from selenium.webdriver.support.ui import Select  # 导入Select类
driver = webdriver.Chrome()
# 打开示例网页
driver.get('https://www.17sucai.com/pins/demo-show?id=5926')
time.sleep(3)
# 切换iframe
driver.switch_to.frame(driver.find_element_by_id('iframe')) # 将driver.switch_to_frame换成driver.switch_to
# 定位select标签
select_tag = Select(driver.find_element_by_id('dk_container_country-nofake')) # 将之前定位到的'nojs'标签当作参数传递进去

select_tag.select_by_index(4)
'''
Message: Select only works on <select> elements, not on <div>
报错Select只能适用于<select> elements元素。
'''

我们就不加Select选择了,而是用查找普通标签的方法,注意看注释:

from selenium import webdriver
import time
from selenium.webdriver.support.ui import Select  # 导入Select类
driver = webdriver.Chrome()
# 打开示例网页
driver.get('https://www.17sucai.com/pins/demo-show?id=5926')
time.sleep(3)
# 切换iframe
driver.switch_to.frame(driver.find_element_by_id('iframe')) # 将driver.switch_to_frame换成driver.switch_to
# 定位select标签
# select_tag = Select(driver.find_element_by_id('dk_container_country-nofake')) # 将之前定位到的'nojs'标签当作参数传递进去
div_tag = driver.find_element_by_id('dk_container_country-nofake')  # 先找到输入框
div_tag.click() # 这里不是select标签,必须要有点击动作
time.sleep(3)
aim_tag = driver.find_element_by_xpath('//*[@id="dk_container_country-nofake"]/div/ul/li[5]/a') # 这里右键标签可以直接复制xpath路径
time.sleep(3)
aim_tag.click() # 仍然要加上点击动作
time.sleep(3)
driver.close()

这次页面打开,Japan被选中,3秒后网页自动关闭。

6. 模拟登录豆瓣

下面我们用模拟登录豆瓣的案例总结一下所学知识点,仔细看注释:

from selenium import webdriver
import time
from selenium.webdriver.support.ui import Select  # 导入Select类,在这个案例里这个没有用
driver = webdriver.Chrome()
# 打开豆瓣网页
driver.get('https://www.douban.com/')
time.sleep(1)
# 切换到账号密码登录界面
driver.find_element_by_xpath('/html/body/div[1]/div[1]/ul[1]/li[2]').click()
time.sleep(1)
# 切换iframe
login_tag = driver.find_element_by_xpath('//*[@id="anony-reg-new"]/div/div[1]/iframe')
driver.switch_to.frame(login_tag) # 将driver.switch_to_frame换成driver.switch_to

# 切换到账号密码登陆方式,这个是在切换到iframe页面后的标签路径
driver.find_element_by_xpath('/html/body/div[1]/div[1]/ul[1]/li[2]').click()
time.sleep(1)
# 输入账号,这个是在切换到iframe页面后的标签路径
acount_tag = driver.find_element_by_xpath('//*[@id="username"]')
acount_tag.send_keys('###########')
time.sleep(1)
# 输入密码,这个是在切换到iframe页面后的标签路径
code_tag = driver.find_element_by_xpath('//*[@id="password"]')
code_tag.send_keys('#########')
time.sleep(2)
button_tag = driver.find_element_by_xpath('/html/body/div[1]/div[2]/div[1]/div[5]/a').click()

这次课就到这里结束。

猜你喜欢

转载自blog.csdn.net/m0_46738467/article/details/112974412