八、selenium

动态HTML技术了解
  • JS
    • 是网络上最常用的脚本语言,它可以收集用户的跟踪数据,不需要重载页面直接提交表单,在页面嵌入多媒体文件,甚至运行网页
  • jQuery
    • jQuery是一个快速、简洁的JavaScript框架,封装了JavaScript常用的功能代码
  • ajax
    • ajax可以使用网页实现异步更新,可以在不重新加载整个网页的情况下,对网页的某部分进行更新
获取ajax数据的方式
  • 直接分析ajax调用的接口。然后通过代码请求这个接口。
  • 使用Selenium+chromedriver模拟浏览器行为获取数据
    在这里插入图片描述
Selenium+chromedriver获取动态数据

selenium是一个web的自动化测试工具,最初是为网站自动化测试而开发的,selenium可以直接运行在浏览器上,它支持所有主流的浏览器,可以接收指令,让浏览器自动加载页面,获取需要的数据,甚至截屏。

chromedriver是一个驱动Chrome浏览器的驱动程序,使用他才可以驱动浏览器。当然针对不同的浏览器有不同的driver。

  • 下载chromedriver
    淘宝镜像(https://npm.taobao.org/)
    下载完成后,放到不需要权限的纯英文目录下就可以了。
Selenium和Phantomjs入门

Phantomjs案例

from selenium import webdriver
driver = webdriver.PhantomJS()
# 打开百度页面
driver.get('https://www.baidu.com/')
# # 保存截图
# driver.save_screenshot('baidu.png')

# 定位操作(定位到输入框直接写kw,可以往输入框里面写python)
driver.find_element_by_id('kw').send_keys('python')
# 点击百度一下
driver.find_element_by_id('su').click()
# 查看信息
# 查看页面源代码
# print(driver.page_source)
# 当前请求的url地址
print(driver.current_url)
# 保存截图(没有页面,可以通过截图看是否运行)
driver.save_screenshot('pyt2.png')
# 退出浏览器
driver.quit()

Selenium案例

from selenium import webdriver
import time
# 实例化浏览器
driver = webdriver.Chrome()

# 窗口最大化
driver.maximize_window()

# 打开网址
driver.get('https://www.baidu.com/')

time.sleep(3)

# 关闭当前窗口
driver.close()
time.sleep(1)

# 退出浏览器
driver.quit()

定位元素

from selenium import webdriver
from selenium.webdriver.common.by import By
import time

driver = webdriver.Chrome()

driver.get('https://www.baidu.com/')

# 通过ID定位
driver.find_element_by_id('kw').send_keys('python')
# driver.find_element(By.ID, 'kw').send_keys('python')

# 通过class_name定位
driver.find_element_by_class_name('s_ipt').send_keys('python')
# driver.find_element(By.CLASS_NAME, 's_ipt').send_keys('python')

# 通过name属性定位
driver.find_element_by_name('wd').send_keys('python')
# driver.find_element(By.NAME, 'wd').send_keys('python')

# 通过标签名字
head = driver.find_element_by_tag_name('head')
# 获取页面所有的input标签
inputTag = driver.find_elements_by_tag_name('input')
# 获取页面源代码
# print(driver.page_source)
# print(len(inputTag))
# print(head)

# 通过xpath
driver.find_element_by_xpath('//input[@id="kw"]').send_keys('java')

# 通过css选择器  .是class  #是id
driver.find_element_by_css_selector('.s_ipt').send_keys('python')

time.sleep(2)
driver.close()

find_element是获取第一个满足条件的元素,find_elements是获取所有满足条件的元素。

操作表单元素
操作输入框:分为两步。
第一步:找到这个元素。
第二步:使用send_keys(value),将数据填充进去。

from selenium import webdriver
import time

driver = webdriver.Chrome()

driver.get('https://www.baidu.com/')

# 定位
inputTag = driver.find_element_by_id('kw')

# 输入
inputTag.send_keys('java')

# 睡眠
time.sleep(2)

# 清除
inputTag.clear()

操作checkbox:因为要选中checkbox标签,在网页中是通过鼠标点击的。因此想要选中checkbox标签,那么先选中这个标签,然后执行click事件。

from selenium import webdriver
from selenium.webdriver.support.ui import Select

driver = webdriver.Chrome()

driver.get('https://www.17sucai.com/pins/demo-show?id=5926')

driver.switch_to.frame(driver.find_element_by_id('iframe'))

selectTag = Select(driver.find_element_by_class_name('nojs'))

# 选择方式
# 1、根据值来选择
# selectTag.select_by_value('JP')

# 2、根据索引来选择
selectTag.select_by_index(2)

登录豆瓣练习

from selenium import webdriver
import time

driver = webdriver.Chrome()

driver.get('https://www.douban.com/')
# 设置页面打开后的大小
driver.set_window_size(1000, 1000)

# 定位
login_frame = driver.find_element_by_xpath('//div[@class="login"]/iframe')

# 切换iframe
driver.switch_to.frame(login_frame)

# 睡眠2秒
time.sleep(2)

# 点击密码登录
# driver.find_element_by_class_name('account-tab-account').click()
driver.find_element_by_xpath('//li[@class="account-tab-account"]').click()

# 点击下次自动登录
driver.find_element_by_id('account-form-remember').click()

# 写账号和密码
driver.find_element_by_id('username').send_keys('xxxx')
driver.find_element_by_id('password').send_keys('xxxx')

# 点击登录豆瓣(这个class不允许中间有空格,如果中间有空格可能是两个class,去掉其中一个,留下的另一个确保在页面代码中只能找到这一个)
driver.find_element_by_class_name('btn-account').click()

行为链
有时候在页面中的操作可能要有很多步,那么这个时候可以使用鼠标行为链类ActionChains来完成。

from selenium import webdriver
from selenium.webdriver.common.action_chains import ActionChains

driver = webdriver.Chrome()

driver.get('https://www.baidu.com/')

# 定位
inputTag = driver.find_element_by_id('kw')
submitBtn = driver.find_element_by_id('su')

actions = ActionChains(driver)

# 输入
actions.send_keys_to_element(inputTag, 'python')

# 点击
actions.move_to_element(submitBtn)
actions.click()

# 提交行为链上的操作(一定要提交,不然上面写的代码无法运行)
actions.perform()

还有更多的鼠标相关的操作

  • click_and_hold(element):点击但不松开鼠标
  • context_click(element):点击右键
  • double_click(element):双击
    更多方法请参考:http://selenium-python.readthedocs.io/api.html

Cookie操作

from selenium import webdriver

driver = webdriver.Chrome()

driver.get('https://www.baidu.com/')
# 获取所有的cookie
cookies = driver.get_cookies()
for cookie in cookies:
    print(cookie)

print('='*30)
# 根据名字获取cookie
print(driver.get_cookie('BD_HOME'))
# 按照名字删除cookie
driver.delete_cookie('BD_HOME')

页面等待
现在的网页越来越多采用Ajax技术,这样程序便不能确定何时某个元素完全加载出来了。如果实际页面等待时间过长导致某个dom元素还没出来,但是你的代码直接使用了这个WebElement,那么就会抛出NullPointer的异常。为了解决这个问题。所以Selenium提供了两种等待方式:一种是隐式等待、一种是显式等待

  • 隐式等待:调用driver.implicitly_wait。那么在获取不可用的元素之前,会先等待输入的时间。
  • 显示等待:显示等待是表明某个条件成立后才执行获取元素的操作。也可以在等待的时候指定一个最大的时间,如果超过这个时间那么就抛出一个异常。显示等待应该使用selenium.webdriver.support.excepted_conditions期望的条件和selenium.webdriver.support.ui.WebDriverWait来配合完成。
from selenium import webdriver
import time

# driver = webdriver.Chrome()

# driver.get('https://www.baidu.com/')

# 强制等待(少用,会让代码变得很慢)
# time.sleep(2)

# 隐式等待(页面元素未加载出来就会等待十秒钟,)
# driver.implicitly_wait(10)

# driver.find_element_by_id('kw').send_keys('python')

# 显式等待
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

driver = webdriver.Chrome()

driver.get('https://www.baidu.com/')

try:
    element = WebDriverWait(driver, 10).until(
        EC.presence_of_all_elements_located((By.ID, 'kw'))
    )
    time.sleep(2)
finally:
    driver.quit()

一些其他的等待条件

  • presence_of_element_located:某个元素已经加载完毕了。
  • presence_of_all_elements_located:网页中所有满足条件的元素都加载完毕了。
  • element_to_be_clickable:某个元素可以点击了。
    更多条件请参考:http://selenium-python.readthedocs.io/waits.html

打开多窗口和切换页面
有时候窗口中有很多tab页面。这时候肯定是需要进行切换的。selenium提供了一个叫做switch_to_window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到。

from selenium import webdriver
import time

driver = webdriver.Chrome()
# 打开第一个窗口
driver.get('https://www.baidu.com/')
# 打开第二个窗口
driver.execute_script("window.open('https://www.douban.com/')")

# 打印当前的url地址
print(driver.current_url)

# 切换界面
driver.switch_to.window(driver.window_handles[1])
print(driver.current_url)

# 睡眠5秒
time.sleep(5)

# 关闭一个窗口
# driver.close()

# # 全部关闭
driver.quit()

QQ邮箱登录

from selenium import webdriver
import time
# 读取后缀名为ini的文件需要导入
from configparser import ConfigParser

# 先实例化
cfg = ConfigParser()

# 读取(名为password1文件里的,password2下面的,p的内容即密码)
r = cfg.read('password1.ini')
password = cfg.get('password2', 'p')

driver = webdriver.Chrome()

driver.get('https://mail.qq.com/')

# 有iframe要加上iframe
login_frame = driver.find_element_by_id('login_frame')
driver.switch_to.frame(login_frame)

# 点击用账户密码登录
driver.find_element_by_id('switcher_plogin').click()

# 写账号和密码
driver.find_element_by_id('u').send_keys('******')
driver.find_element_by_id('p').send_keys(password)
time.sleep(5)

# 点击登录
driver.find_element_by_id('login_button').click()

拉勾网案例(翻页多了要登录,所以爬取一定数量的信息后会报错)

from selenium import webdriver
import time
from lxml import etree
# 显式等待
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC

class LagouSpider(object):
    def __init__(self):
        self.url = "https://www.lagou.com/jobs/list_python?labelWords=&fromSearch=true&suginput="
        self.driver = webdriver.Chrome()

    def run(self):
        self.driver.get(self.url)
        # 取消页面得弹出框
        self.driver.find_element_by_class_name('body-btn').click()
        # 连续翻页,获取数据
        while True:
            # 获取页面源代码
            source = self.driver.page_source
            self.parse_list_page(source)

            time.sleep(2)
            # 显式等待(并且用xpath判断当前页面有没有最后一页得class pager_next pager_next_disabled)
            next_btn = WebDriverWait(driver=self.driver, timeout=10).until(
                EC.presence_of_element_located((By.XPATH, "//span[contains(@class, 'pager_next')]"))
            )

            # 点击下一页
            # self.driver.find_element_by_class_name('pager_next ').click()

            # 连续翻页得结束条件
            if "pager_next pager_next_disabled" in next_btn.get_attribute('class'):
                break
            else:
                # 有的时候class里面含有空格或其他符号,导致定位不行,可以采用xpath进行模糊定位(contains进行模糊查询,只要class里面包含后面得字符串都可以查出来)
                next_btn.click()

    # 处理列表页面
    def parse_list_page(self, source):
        # 用xpath
        html = etree.HTML(source)

        links = html.xpath("//a[@class='position_link']/@href")
        for link in links:
            # 获取详情页面
            self.requests_detail_page(link)
            time.sleep(2)

    def requests_detail_page(self, link):
        # 打开详情页面
        self.driver.get(link)
        source = self.driver.page_source
        self.parse_detail_page(source)

    def parse_detail_page(self, source):
        html = etree.HTML(source)
        job_name = html.xpath("//div[@class='job-name']/h1/text()")[0]
        job_detail = html.xpath("//div[@class='job-detail']/p/text()")
        print(job_name, job_detail)


if __name__ == '__main__':
    lg = LagouSpider()
    lg.run()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值