解析网页-selenium-非常实用-python爬虫知识点7

2023-11-06

selenium

  • 优点:可以进行互动的操作,处理动态网页
  • 缺点:慢

一、引入

  • 爬虫和反爬虫的斗争在这里插入图片描述
  • selenium最初本来是用来测试网站的,但是爬虫人员将其引过来可以解决动态网页的问题

静态网页与ajax动态加载

  • 以前爬取的网页都是静态的网页
  • 何为静态网页,其实就是我们向一个网站发起请求得到响应,那么这些响应的数据都是网页的源代码中,通过response就可以得到数据
  • 除了静态网页,还有一些网站数数据不在这个请求得到url地址当中,那么这些护具有可能是通过ajax技术加载出来的数据,例如12306的班次的信息不在url中,查询的内容只是对网页的部分内容更新,这个就是ajax动态加载出来的
  • element是最终的显示结果,会经过渲染和多次请求,只能作为参考,只有源代码才是准确的,如果观察element的数据在网页源代码中没有,那就可能藏着其他文件里,动态加载出来的

ajax动态加载的数据怎么处理

  • 网页有我们要爬取的数据,但是网页的源码中没有,该如何解决
    • 1.分析真正的ajax真正的数据接口,找到接口的url。从而来获取数据
    • 2.通过selenium来模拟浏览器获取数据
      +chromedriver模拟浏览器行为获取数据

ajax基本介绍

  • 动态了解HTML技术
    • JS
      • 是网络上最常用的脚本语言,它可以收集用户的跟踪数据,不需要重载页面直接提交表单,在页面嵌入多媒体文件,甚至运行网页
    • jQuery
      • jQuery是一个快速、简介的JavaScript框架,封装了JavaScript常用的功能代码
    • ajax
      • ajax可以使用网页实现异步更新,可以在不重新加载整个网页的情况下,对网页的某部分进行更新

二、配置Selenium、chromdriver

Selenium 介绍

  • selenium是一个web的自动化测试工具,最初是为网站自动化测试而开发的,selenium可以直接运行在浏览器上,它支持所有主流的浏览器,可以接收指令,让浏览器自动加载页面,获取需要的数据,甚至页面截屏
    • 安装Selenium:pip install selenium, 安装教程
    • 要使用Selenium,还要下载浏览器驱动,第一次启用驱动要指定地址,或者将其安装在当前工作目录下

chromedriver

  • chromedriver是一个驱动Chrome浏览器的驱动程序,使用他才可以驱动浏览器。当然针对不同的浏览器有不同的driver。以下列出了不同浏览器及其对应的driver:
  • chromedriver 地址 http://chromedriver.storage.googleapis.com/index.html 选择和浏览器版本匹配的驱动器
  • firefoxdriver类似,火狐浏览器的驱动器

Phantomjs

  • 无头浏览器,不会打开页面,它是没有和用户交互界面的,一个完整的浏览器内核,包括js解析引擎,渲染引擎,请求处理等,但是不包括显示和用户交互页面的浏览器
  • 用途:
    • 1 有的程序是用的是它
    • 2 对比的去学习chromedriver
  • 区别:
    • Phantomjs可以通过截屏driver.save_screenshot(‘baidu.png’)来获取测试结果,不会和 chromedriver一样弹出浏览器窗口,动态看操作步骤。
    • Phantomjs对于Selenium是过时的程序,所以会报错警告

三、Selenium的基本操作

  • from selenium import webdriver
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import Select
  • 当属性有空格的时候,定位的时候可能会找不到该元素,例如account-tab-account on 如何解决呢?
    • 1.可以选其中的一部分(通过测试)先选择长一点的尝试,去掉on
    • 2 xpath来定位
  • 注意:没有网的话用 selenium会报错

(一)设置驱动、退出驱动

driver = webdriver.Chrome(路径)

  • 路径:填的是chromedriver.exe的路径,如果当前工作文件夹有,可以不填
  • Chrome:这个是打开的是Chrome浏览器,也可以选择火狐webdriver.firefox()或无头浏览器webdriver.PhantomJS()

设置无界面模式

  • 设置了这个后就不会再弹出浏览器窗口了,可以截屏,但和不同无头浏览器不完全一样,无头浏览器截屏可以看到它是没有浏览器的,不会有拖动框。
# 创建chrome设置对象
options = webdriver.ChromeOptions()
# 设置无界面功能  --headless 浏览器无界面 --xxxx 
options.add_argument('--headless')
driver = webdriver.Chrome(options=options)

driver.quit()

  • 退出驱动(关闭所有的窗口)

(二)网页打开、关闭等基本操作

1.打开网页、多个网页、切换窗口

打开网页

  • get(url)接连打开两个网页,后面会直接覆盖前面的

如何打开多个窗口呢?

  • driver.execute_script(‘window.open(“https://www.douban.com/”)’)
  • 但是当前工作环境,后面操作对象仍然是前面的窗口,要想在新的窗口进行操作的换,还需要主动的切换窗口
  • 有时候窗口中有很多子tab页面。这时候肯定是需要进行切换的。selenium提供了一个叫做switch_to_window来进行切换,具体切换到哪个页面,可以从driver.window_handles中找到

切换窗口

  • driver.switch_to.window(driver.window_handles[1]) 序号就是代指了网页的顺序索引,从0开始

显示当前窗口

  • driver.current_url
    在这里插入图片描述

2.关闭当前窗口

driver.close()

  • 关闭当前窗口,只会关闭一个,当前如果有多个窗口的话,只会关闭当前工作的窗口
  • 因为关闭的是当前工作的窗口,所以后面再继续操作都会报错,即使打开另一个窗口的操作也不行,这个时候就必须要切换还在的窗口,然后再进行下一个步骤

3.网页全屏与截屏

全屏

  • driver.maximize_window()

网页截屏

  • driver.save_screenshot(‘图片名.png’)`
  • 截取的是当前工作的网页

(三)定位元素

  • 通过定位元素,就可以在指定的位置操作元素

方法

  • element匹配第一个
    elements 匹配所有,返回列表
    • driver.find_element(By.某,对应某值)
      driver.find_elements(By.某,对应某值)
    • driver.find_element_by_ 某(对应某值)
      driver.find_elements_by_ 某(对应某值)

1.通过标签

  • driver.find_element_by_tag_name(‘标签名’)
    driver.find_elements_by_tag_name(‘标签名’)
  • 不够精确,不常用

2.通过属性值

  • id
    • driver.find_element_by_id(‘属性值’) 方法指定属性
      driver.find_elements_by_id(‘属性值’)
    • driver.find_element(By.ID,‘属性值’) 括号指定属性
      driver.find_element(By.ID,‘属性值’)
  • class(by_class_name用的是class_name)、name、link等属性同理

3.通过xpath

  • driver.find_element_by_xpath(xpath路径)
  • 可以直接复制某行的xpath的路径

(四)标签元素处理

1.获取文本text

  • tag.text

2.获取属性值get_attribute('属性')

  • tag.get_attribute(‘属性’)

3.获取文本输入框内容get_attribute('value')

  • InputTag.get_attribute(‘value’)

(五)操作元素

1.输入框-----传值send_key()与清空值clear()

send_key()传值

  • 第一步:找到这个元素input_tag,定位到的输入框标签位置。
    第二步:使用send_keys(value),将数据填充进去
    input_tag.send_keys(‘要传的值’)

clear()清空值

  • input_tag.clear()清空输入值
    在这里插入图片描述在这里插入图片描述在这里插入图片描述

2.按钮-----click()点击

  • 操作按钮有很多种方式。比如单击、右击、双击等。这里讲一个最常用的。就是点击

click()点击

  • 第一步:找到这个元素button,定位到的按钮标签位置。
    第二步:使用.click()
    button.click()
    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

3.下拉框-----select与非select

在这里插入图片描述

select

  • 定位这个select标签 以参数形式传递进去
  • 以什么方式来选择下拉框的选项
    • 根据值来选择
    • 根据索引来选择
# select标签
selectTag = Select(driver.find_element_by_class_name('nojs'))
# 选择方式
# 1 根据值来选择
selectTag.select_by_value('JP')
# 2 根据索引来选择
selectTag.select_by_index(2)

非select

  • 先定位选择框的位置
  • 再定位选项的位置
  • 点击选项的位置
# 非select标签
# 1.定位选择框并点击
divTag = driver.find_element_by_id('dk_container_country_nofake').click()
# 2.定位到要选择值的位置并点击
driver.find_element_by_xpath('xpath路径').click()

4.翻页

在不知道有多少页数的情况下进行翻页

  • 第一种:不断点击下一页,针对最后一页没有下一页的按钮
    try:
        # 找不到下一页,就是最后一页,就会抛出异常 此时就证明是最后一页了
        driver.find_element_by_link_text('下一页').click()
    except Exception as e:
        driver.quit()
        break
  • 第二种:判断是否是最后一页,针对最后一页有下一页按钮,但是无法点击
       while True:
            self.pares_html()
            # 在最后一页的时候,找到特殊的属性
            if self.driver.page_source.find('pn-next disable') == -1:
                self.driver.find_element_by_xpath(下一页的标签元素位置xpath路径).click()
                time.sleep(1)
            else:
                self.driver.quit()
                break

5.往下拉拖拽

  • 针对那些ajax动态加载的网站,边往下拉,边生成响应文件
  • 需要手动下拉加载全部的信息
  • driver.execute_script(
    ‘window.scrollTo(0,document.body.scrollHeight)’
    )
class Spider():
    def pares_html(self):
# 进入这个页面的时候,把这个拖动条拖动一下,拖到最下面,把页面全部加载出来
        # 0 是从去起始位置开始
        # document.body.scrollHeight 整个窗口的高度
        self.driver.execute_script(
            'window.scrollTo(0,document.body.scrollHeight)'
        )
        time.sleep(3)  

(六)其他操作

1.有iframe的标签------切换iframe

  • frame 是HTML的标签 作用:文档中的文档 所以如果有iframe标签 而这个标签里面嵌套的内容正好就有你要操纵的元素,此时此刻就需要先切换iframe
  • 不切换的话会报错,会找不到不要查询的元素
  • 定位到你要操作的地方的iframe标签位置
    driver.switch_to.frame(定位的位置)
    driver.switch_to_frame(定位的位置) 过时,但是还是可以用
    在这里插入图片描述

2.判断是否存在某字段

  • driver.page_source.find
    • driver.page_source.find(字段),用拿到的全部的网页信息来find我们要的信息,如果找不到会返回-1,找到的话返回的位置数字
    • 区别:driver.find_element…这个没有找到会直接报错,可以和try except搭配,而driver.page_source.find找不到会返回-1
    • 相同:最终element呈现的结果,也就是页面有的信息全都可以找到
 if self.driver.page_source.find(标签里的字段) == -1:  #判断该页面是否存在该标签

3.鼠标行为链

鼠标有啥行为和动作:双击、右键、单击、选中、拖拽…

  • from selenium.webdriver import ActionChains

  • 实例化对象

    • actions = ActionChains(driver)
  • 提交行为链

    • actions.perform()
      实现所有行为链操作,最后要提交行为链,实施决策
  • 传值

    • inputTag = driver.find_element…
    • actions.send_keys_to_element(inputTag,要传的值)
      区别:普通的是inputTag.send_key()
  • 点击

    • buttonTag = driver.find_element…定位到的按钮标签位置
    • actions.move_to_element(buttonTag) 将光标移动到按钮的位置
    • actions.click() 执行点击动作
      不能直接buttonTag.click(),不要在鼠标行为链里面出现,要放在提交行为链后面才能使用
  • 更多的鼠标相关的操作
    • click_and_hold(element):点击但不松开鼠标。
    • context_click(element):右键点击。
    • double_click(element):双击。
    • 更多方法请参考:http://selenium-python.readthedocs.io/api.html

4.模拟登入

  • 选择登入方式,多种多样,根据登陆页面相应操作后,左后点击登入按钮
  • 输入账号密码/扫描/点击头像自动登入

账号密码登入

# 选择账号密码登入方式
driver.find_element_by_class_name('account-tab-account').click()
time.sleep(2)
# 定位账号和密码 并输入内容
driver.find_element_by_id('username').send_keys('xxxxxx')
time.sleep(1)
driver.find_element_by_id('password').send_keys('xxxxxx')

扫描登入

login_url = 'https://kyfw.12306.cn/otn/resources/login.html' # 登录的url
personal_url = 'https://kyfw.12306.cn/otn/view/index.html' # 个人中心的url
 driver.get(login_url)
 # 检测是否因为扫码成功url跳转到个人中心,登录也是一个耗时的操作
 WebDriverWait(driver, 1000).until(
     EC.url_contains(personal_url)
 )
 print('登录成功!')

点击头像自动登入

  • 仅使用那些后台已经登入后,只需要点击头像就可以自动登陆,很多qq登陆会支持这个功能
# 只需要点击头像就可以登陆的url
driver.get('https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https%3A//qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https%3A%2F%2Fqzs.qzone.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&pt_qr_app=手机QQ空间&pt_qr_link=http%3A//z.qzone.com/download.html&self_regurl=https%3A//qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=http%3A//z.qzone.com/download.html&pt_no_auth=0')

# 等待加载出后台登陆的信息
time.sleep(1)
# 定位头像位置
button = driver.find_element_by_class_name('face')
# 点击头像即登陆
button.click()

5.get_cookies()获取cookie

  • driver.get_cookies() 返回列表
  • 作用:因为有些网页要登入才能访问,但过段时间cookie会失效,所以可以通过模拟登入来获取最新cookie
  • 操作步骤:1 要通过selenium点击登入,并获取cookie值 2.解析这个cookie值 3.require请求头加入这个cookie
# 处理成可以用来爬虫的cookie信息cookie_str来模拟登入
listCookies = driver.get_cookies()  返回列表
cookie = [item['name'] + '=' + item['value'] for item in listCookies ] # cookies藏在name和value信息里
cookie_str = '; '.join(item for item in cookie)

四、wait页面等待

为什么要等?

  • 1 selenium比较慢 网站打开了 元素没有加载出来
    2 有些数据是通过ajax加载的

如何解决?

  • time.sleep() 靠谱 Python提供的,强制等待
  • selenium也提供了页面等待的方式,只要找到元素就立即执行,超过这个时间那么就抛出一个异常。
    • 1.隐式等待:driver.implicitly_wait(秒数)全局的等待时间
    • 2.显示等待:WebDriverWait(driver,秒数).until(条件) ,显示等待是表明某个条件成立后才执行获取元素的操作。

显示等待模块WebDriverWait与EC

  • from selenium.webdriver.support import expected_conditions as EC
    from selenium.webdriver.common.by import By
    from selenium.webdriver.support.ui import WebDriverWait
  • 常用的 EC.text_to_be_present_in_element_value
    、EC.presence_of_element_located、EC.element_to_be_clickable、EC.url_contains()

(一)title标题

(1) EC.title_is :网页标题是否显示特定内容(必须完全符合),如果是返回True,否则返回False

  • WebDriverWait(driver,秒数).until(EC.title_is(‘字段’))
result = EC.title_is('百度一下,你就知道')
print(result(self.driver))  # True
WebDriverWait(driver,2).until(result)  # True

(2)EC.title_contains :网页标题是否包含特定内容,如果是返回True,否则返回False

  • WebDriverWait(driver,秒数).until(EC.title_contains(‘字段’))
  result = EC.title_contains('百度')
  print(result(self.driver))  # True
  WebDriverWait(driver,2).until(EC.title_contains('百度') # True

(二)url网址

(1)url_containsurl是否包含特定内容,如果是返回True,否则返回False

  • WebDriverWait(driver,秒数).until(EC.title_contains(‘部分字段’)
result = EC.url_contains('baidu')
print(result(self.driver))  # True
WebDriverWait(driver,2).until(EC.title_contains('百度') # True

(2)url_matches正则匹配url,网页网址是否匹配特定内容,如果是返回True,否则返回False

  • WebDriverWait(driver,秒数).until(EC.url_matches(pattern))
  • pattern是匹配url的正则表达式样式
#url是https://www.baidu.com/
pattern = r'.*?baidu.*?' #使用正则表达式,规定网址格式(格式要求以https开头)
result = EC.url_contains(pattern)
print(result(self.driver))  # True
WebDriverWait(driver,秒数).until(EC.url_matches(pattern)) # True

(3)url_to_be :网页网址是否显示特定网址(必须完全符合),如果是返回True,否则返回False

  • WebDriverWait(driver,秒数).until(EC.url_to_be(url))
result = EC.url_to_be('https://www.baidu.com')
print(result(self.driver))
WebDriverWait(driver,秒数).until(EC.url_to_be('https://www.baidu.com')) 

(三)element元素显示与可见

(1)presence_of_element_located特定元素是否存在于页面中,如果是,返回该元素(单个元素),否则报错

  • WebDriverWait(driver,秒数).until(EC.presence_of_element_located(locator))
  • locator = (By.CLASS_NAME, ‘lh’) # 类似的定位元素
locator = (By.CLASS_NAME, 'lh')  #定位class='lh'的元素
result = EC.presence_of_element_located(locator)
print(result(self.driver))
WebDriverWait(driver,2).until(EC.presence_of_element_located(locator))

(2)presence_of_all_elements_located :定位的元素范围内,是否至少有一个元素存在于页面当中,如果是,返回满足条件的所有元素组成的List,否则返回空List

  • WebDriverWait(driver,秒数).until(EC.presence_of_all_elements_located(locator))
locator = (By.CLASS_NAME, 'lh') #定位所有class='lh'的元素
result = EC.presence_of_all_elements_located(locator)
print(result(self.driver))

(3)visibility_of_element_located :特定元素是否存在于网页中并可见,如果是返回该元素(单个元素),否则报错

  • WebDriverWait(driver,秒数).until(EC.visibility_of_element_located(locator))
locator = (By.CLASS_NAME, 'hl')
result = EC.visibility_of_element_located(locator)
print(result(self.driver))
WebDriverWait(driver,2).until(EC.visibility_of_element_located(locator))

元素可见:元素的高和宽都大于0

  • 注:visibility_of_element_located与 presence_of_element_located作用类似,但前者无所谓可见与否,所以在性能上略胜一筹。

(4)invisibility_of_element_located: 特定元素是否不可访问或不存在于DOM树中,如果不存在则返回True,否则返回True

  • 注:invisibility_of_element_located :刚好与 visibility_of_element_located的作用相反,且返回的结果大不相同。

(5)invisibility_of_element: 特定元素是否不可访问或不存在于DOM树中,如果不存在则返回True,否则返回True

  • 注:invisibility_of_element_located与 invisibility_of_element作用类似,但前者传的是定位范围locator,后者可以是定位范围(仅text文本),也可以是元素element。

(6)visibility_of: 特定元素是否存在于DOM树中并可见,如果是返回该元素(单个元素),否则报错

element = self.driver.find_element_by_id('kw')
result = EC.visibility_of(element)
print(result(self.driver))
  • 注:visibility_of_element_located与 visibility_of作用类似,但是前者传入的是定位范围locator,后者传入的是元素element,另外 invisibility_of_element与 visibility_of作用相反,且返回的结果大不相同。

(7)visibility_of_any_elements_located: 定位的元素范围内,是否至少有一个元素存在于DOM树中并可见,如果是,返回满足条件的所有元素组成的List,否则返回空List

(8)visibility_of_all_elements_located: 定位的元素范围内,是否所有元素都存在于DOM树中并且可见,如果是,以List形式返回元素,否则返回False

(9)element_to_be_clickable: 特定元素是否可点击,如果可以则返回该元素,否则返回False

  • WebDriverWait(driver,秒数).until(EC.element_to_be_clickable(locator))
locator = (By.ID, 'su') #是一个可点击的按钮
result= EC.element_to_be_clickable(locator)
print(result(self.driver))
WebDriverWait(driver,2).until(EC.element_to_be_clickable(locator))

(四)text文本----element

(1)text_to_be_present_in_element:特定文本是否出现在特定元素中,如果是则返回True,否则返回False

  • WebDriverWait(driver,秒数).until(EC.text_to_be_present_in_element(locator,文本))
locator = (By.ID, 'su')
element = EC.text_to_be_present_in_element(locator, 'submit') #查看中是否包含'submit'
print(element(driver))
WebDriverWait(driver,2).until(EC.text_to_be_present_in_element(locator, 'submit'))

(2)text_to_be_present_in_element_value:判断某文本是否是存在于特定元素的value值中,如果是则返回True,否则返回False

  • WebDriverWait(driver,2).until(EC.text_to_be_present_in_element_value(locator, 属性value属性值) )
locator = (By.ID, 'su')
element = EC.text_to_be_present_in_element_value(locator, '百度一下') #查看的value值中是否包含'百度一下'
print(element(driver))
WebDriverWait(driver,2).until(EC.text_to_be_present_in_element_value(locator,  '百度一下') )
  • 注:如果该特定元素没有value值,也会返回False

(五)frame

(1)frame_to_be_available_and_switch_to_itframe:窗口是否可被切换,如果是返回True,否则返回False

  • WebDriverWait(driver,2).until(EC.text_to_be_present_in_element_value(locator, ‘百度一下’) )

(六)windows窗口

(1)number_of_windows_to_be:特定窗口数和实际窗口数是否一致,如果是返回True,否则返回False

  • WebDriverWait(driver,秒数).until(EC.number_of_windows_to_be(个数) )
windows = EC.number_of_windows_to_be(2) #期望窗口设置为2个
print(windows(self.driver))
WebDriverWait(driver,10).until(ECnumber_of_windows_to_be(2) )

(2)new_window_is_opened:新窗口是否打开,如果是返回True,否则返回False

  • WebDriverWait(driver,秒数).until(EC.new_window_is_opened(driver.window_handles) )
current_handles = self.driver.window_handles #获得当前所有句柄数量
new_window = EC.new_window_is_opened(current_handles)
print(new_window(self.driver))
WebDriverWait(driver,10).until(EC.new_window_is_opened(current_handles) )

(七)alert对话框

(1)alert_is_present:弹出框是否存在,如果是,切换到alert,否则返回false

  • WebDriverWait(driver,秒数).until(EC.alert_is_present() )
alert = EC.alert_is_present()
WebDriverWait(driver,秒数).until(EC.alert_is_present() )
#操作alert,例如:关闭alert
alert.accpet()

五、Selenium的常见错误

未联网

  • Message: unknown error: net::ERR_INTERNET_DISCONNECTED
    (Session info: chrome=90.0.4430.212)

没有切换iframe

  • Message: no such element: Unable to locate element: {“method”:“css selector”,“selector”:".account-tab-account"}
    (Session info: chrome=90.0.4430.212)
    会报错说显示找不到元素
  • 解决办法:查看定位的元素是否在iframe标签下,如果是,就要先定位iframe标签,并切换到该标签下,加上这两行就可以解决
  • login_frame = driver.find_element_by_xpath(’//*[@id=“anony-reg-new”]/div/div[1]/iframe’) 括号填的就是iframe标签的xpath路径
    driver.switch_to.frame(login_frame)

JS加载,hidden

按钮无法点击

  • 有些按钮用Selenium就是无法点击没在这种情况下,我们采用其他办法
  • 解决办法:
    • btn = driver.find_element_by_id(‘query_ticket’)
      driver.execute_script(‘arguments[0].click()’,btn) 固定的元素,使用这种方法点击代替btn.click()

元素无法传值

  • type中含有hidden,无法传值
  • driver.execute_script(‘arguments[0].value="%s"’ % 输入框的值, 输入框的定位元素对象)

六、Selenium的实例

(一)模拟登录—豆瓣和12306

模拟登录豆瓣

  • 利用的是定位、传值与点击
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import Select
import time

driver = webdriver.Chrome(r"C:\Users\lenovo\Desktop\chromedriver.exe")
driver.get('https://www.douban.com/')
# 切换iframe 
login_frame = driver.find_element_by_xpath('//*[@id="anony-reg-new"]/div/div[1]/iframe')
driver.switch_to.frame(login_frame)

# 切换登录方式 千万不要忘记click()   当属性有空格的时候 account-tab-account on 如何解决呢?1.可以选其中的一部分(通过测试)先选择长一点的尝试 2 xpath来定位
driver.find_element_by_class_name('account-tab-account').click()
time.sleep(2)
# 定位账号和密码 并输入内容
driver.find_element_by_id('username').send_keys('xxxxxx')
time.sleep(1)
driver.find_element_by_id('password').send_keys('xxxxxx')

# 点击登录按钮
driver.find_element_by_class_name('btn').click()

在这里插入图片描述
模拟登录12306

  • 扫码登陆
from selenium import webdriver
import time
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()

# 面向对象来实现
# 类是一个创建对象的对象 希望必须做一些事情 不做这个类就创建不成功
class TrainSpider(object):
    login_url = 'https://kyfw.12306.cn/otn/resources/login.html' # 登录的url
    personal_url = 'https://kyfw.12306.cn/otn/view/index.html' # 个人中心的url

    def __init__(self,from_station,to_station,train_data):
        self.from_station = from_station
        self.to_station = to_station
        self.train_data = train_data

    def login(self):
        driver.get(self.login_url)

        # 登录也是一个耗时的操作
        WebDriverWait(driver, 1000).until(
            EC.url_contains(self.personal_url)
        )

        print('登录成功!')


    # run一般用来封装了我们基本的功能
    def run(self):
        # 登录
        self.login()


def main():
    spider = TrainSpider('北京','长沙','2021-05-19')# 日期格式需要注意2021-05-19
    spider.run()


if __name__ == '__main__':
    main()

(二)获取cookie–模拟登入QQ空间

qq登入第三方界面:点击头像就可以登入的方式

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

# 模拟登录QQ空间
# 携带cookie进行模拟 也就是我们先通过正常的途径进行登录此时此刻就可以获得一个cookie.然后在正常的编写一个 模拟登录的逻辑就可以啦
# 下面的逻辑 1 要通过selenium获取 qq空间的cookie值 2 解析这个cookie值 3 进行测试
driver = webdriver.Chrome(r"C:\Users\lenovo\Desktop\chromedriver.exe")
# 不要删参数  加载第三方的登录方式,需要后台登陆了qq
driver.get('https://xui.ptlogin2.qq.com/cgi-bin/xlogin?proxy_url=https%3A//qzs.qq.com/qzone/v6/portal/proxy.html&daid=5&&hide_title_bar=1&low_login=0&qlogin_auto_login=1&no_verifyimg=1&link_target=blank&appid=549000912&style=22&target=self&s_url=https%3A%2F%2Fqzs.qzone.qq.com%2Fqzone%2Fv5%2Floginsucc.html%3Fpara%3Dizone&pt_qr_app=手机QQ空间&pt_qr_link=http%3A//z.qzone.com/download.html&self_regurl=https%3A//qzs.qq.com/qzone/v6/reg/index.html&pt_qr_help_link=http%3A//z.qzone.com/download.html&pt_no_auth=0')

# 等待加载出登入的头像
time.sleep(2)

#点击登入的地方的标签
button = driver.find_element_by_class_name('face')
# 进行点击
button.click()
#等待登入界面打开
time.sleep(2)
#获取cookies
listCookies = driver.get_cookies() 
cookie = [item['name'] + '=' + item['value'] for item in listCookies]
cookie_str = '; '.join(item for item in cookie)

# 目标url,登入界面
url = 'https://user.qzone.qq.com/自己的QQ号'

headers = {
    'cookie':cookie_str,
    'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.212 Safari/537.36'
}

html = requests.get(url,headers=headers)
time.sleep(2)
# 写入个人界面的源代码
with open('qzong.html','w',encoding='utf-8') as file_obj:
    file_obj.write(html.text)
print(html.text)

(三)翻页–爬取猫眼电影

  • 用到点击下一页的翻页
    在这里插入图片描述
from selenium import webdriver
import csv

class maoyanSpider(object):   
    
    def __init__(self):
        # 创建chrome设置对象 程序没有问题在去设置 无界面模式
        self.options = webdriver.ChromeOptions()
        # 设置无界面功能  --headless 浏览器无界面  --xxxx
        self.options.add_argument('--headless')
        self.driver = webdriver.Chrome(options=self.options)
        self.driver.get('https://maoyan.com/board/4')
        
     
    def get_one_page(self):
    # 找到这一页的dd标签,就是电影的标签,找到dd不止一个用elements
        movielist = []
        dd_lst = self.driver.find_elements_by_xpath('//*[@id="app"]/div/div/div[1]/dl/dd')
        for dd in dd_lst:
            # text属性 获取当前dd节点的子节点以及后代节点的文本内容
            # 视情况而分析 验证我们打印的内容有什么规律吗?如果有 就进一步操作
            # 这里有规律,所以直接对字符串切分,然后通过序号索引就行
            # print(dd.text)
            # print('*'*80)
            one_film_info_lst = dd.text.split('\n')

            try:
                rank = one_film_info_lst[0].strip()
                name = one_film_info_lst[1].strip()
                actor = one_film_info_lst[2].strip()
                time = one_film_info_lst[3].strip()
                score = one_film_info_lst[4].strip()
            except:
                pass
            movielist.append((rank,name,actor,time,score))
        return movielist
            
            
    def saveData(self):
        header = ['排名','电影名','演员','年份','评分']
        with open('maoyanMovie.csv','w',encoding='utf-8',newline='') as file_obj:
            writer = csv.writer(file_obj)
            writer.writerow(header)
            while True:
                writer.writerows(self.get_one_page())
                # 如果最后一定会报错的话,用try、except比if更好用
                try:
                    # 找不到最后一页 就会抛出异常 此时就证明是最后一页了
                    self.driver.find_element_by_link_text('下一页').click()
                except Exception as e:
                    driver.quit()
                    break
                
                
if __name__=='__main__':
    main = maoyanSpider()
    main.saveData()

在这里插入图片描述

(四)翻页拖拽–爬取京东商品信息

  • 输入关键字,观察京东商品页面会发现,往下拉动的时候会动态弹出一部分的商品信息,是不包含在网页源代码里面的,会再次获得另一个响应结果(文件),所以是ajax动态加载出来的文件

  • 页面分析

    • 我们发现 所有的数据都是在一个ul标签 ul标签下面每一个li标签对应的就是一个商品介绍。
    • 我们拖动 拖动条(滚轮)的时候 页面又加载了数据
      当我们进入这个页面的时候,把这个拖动条拖动一下,拖到最下面,然后等它加载一会儿,等页面元素加载完了之后,我们再去抓取
    • 每页 上来先加载30个 当我们进行拖动的时候 它又会加载30个 也就是每页其实是60个数据
  • 对于这种动态加载文件:

    • 1.找到动态加载文件url的规律,分别请求得到信息
    • 2.利用selenium拖拽到底部,让页面的元素全部加载出来
from selenium import webdriver
import time
import csv


class JdSpider():
    def __init__(self,good_name):
        
        self.good_name = good_name
        # 设置无界面
        self.options = webdriver.ChromeOptions()
        # 设置无界面功能  --headless 浏览器无界面  --xxxx
        self.options.add_argument('--headless')
        self.driver = webdriver.Chrome(options=self.options)
        self.driver.get('https://www.jd.com/')
        # 定位输入框和按钮
        self.driver.find_element_by_xpath('//*[@id="key"]').send_keys(self.good_name)
        time.sleep(1)
        self.driver.find_element_by_xpath('//*[@id="search"]/div/div[2]/button').click()
        time.sleep(1)


    def pares_html(self):

        # 进入这个页面的时候,把这个拖动条拖动一下,拖到最下面
        # 0 是从去起始位置开始
        # document.body.scrollHeight 整个窗口的高度
        self.driver.execute_script(
            'window.scrollTo(0,document.body.scrollHeight)'
        )
        time.sleep(3)

        # 提取数据 千万不要忘记写li
        li_lst = self.driver.find_elements_by_xpath('//*[@id="J_goodsList"]/ul/li')
        item = []
        for li in li_lst:
            # print(li.text)
            # print('*'*50)
            try:
                price = li.find_element_by_xpath('.//div[@class="p-price"]/strong').text.strip()
                name = li.find_element_by_xpath('.//div[@class="p-name"]/a/em').text.strip()
                commit = li.find_element_by_xpath('.//div[@class="p-commit"]/strong').text.strip()
                shop = li.find_element_by_xpath('.//div[@class="p-shopnum"]/a').text.strip()
            except Exception as e:
                print(e)
                
            item.append((price,name,commit,shop))
            
        return item
  
                
    def saveData(self):
        header = ['价格','商品名','评价','店铺']
        with open('JD'+self.good_name+'.csv','w',encoding='utf-8',newline='') as file_obj:
            writer = csv.writer(file_obj)
            writer.writerow(header)
            while True:
                writer.writerows(self.pares_html())
                # 如果最后一定会报错的话,用try、except比if更好用
                # 这个代码是一直爬取到最后一页,如果不需要那么多可以手动停止,或者改成爬取页面页数限制
                if self.driver.page_source.find('pn-next disable') == -1:
                    self.driver.find_element_by_xpath('//*[@id="J_bottomPage"]/span[1]/a[9]').click()
                    time.sleep(1)
                else:
                    self.driver.quit()
                    break


if __name__ == '__main__':
    good_name = input('请输入你要查询的商品的关键字:')
    spider = JdSpider(good_name)
    spider.saveData()

在这里插入图片描述

(五)关闭弹窗+显示等待+按钮无法点击–爬取12306网站信息

from selenium import webdriver
import time
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://kyfw.12306.cn/otn/leftTicket/init?linktypeid=dc')
driver.implicitly_wait(3)

# 关闭提示框
driver.find_element_by_id('gb_closeDefaultWarningWindowDialog_id').click()

# 显示等待,等待出发地加载出来,这个时候你需要自己手动的在页面添加城市信息,当页面检测出来后,就会自动的弹出车次信息
WebDriverWait(driver,1000).until(
    EC.text_to_be_present_in_element_value((By.ID,'fromStationText'),'北京')
)

# 等待目的地加载出啦
WebDriverWait(driver,1000).until(
    EC.text_to_be_present_in_element_value((By.ID,'toStationText'),'长沙')
)


btn = driver.find_element_by_id('query_ticket')
# 按钮不能够被点击
driver.execute_script('arguments[0].click()',btn)
# btn.click()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

解析网页-selenium-非常实用-python爬虫知识点7 的相关文章

  • xlrd.biffh.XLRDError:Excel xlsx 文件;不支持[重复]

    这个问题在这里已经有答案了 我正在尝试使用读取启用宏的 Excel 工作表pandas read excel与 xlrd 库 它在本地运行良好 但是当我尝试将其推送到 PCF 时 我收到此错误 2020 12 11T21 09 53 441
  • Flask+Nginx+uWSGI:导入错误:没有名为站点的模块

    我安装为http www reinbach com uwsgi nginx flask virtualenv mac os x html http www reinbach com uwsgi nginx flask virtualenv
  • Kivy - 文本换行工作错误

    我正在尝试在 Kivy 1 8 0 应用程序中换行文本 当没有太多文字时 一切正常 但如果文本很长并且窗口不是很大 它只是剪切文本 这是示例代码 vbox BoxLayout orientation vertical size hint y
  • 如何使用显式引用转储 YAML?

    递归引用非常适合ruamel yaml or pyyaml ruamel yaml dump ruamel yaml load A A id001 id001 然而 它 显然 不适用于普通引用 ruamel yaml dump ruamel
  • 如何在 PyCharm 4.5.2 中使用 PyPy 作为标准/默认解释器?

    如何在 PyCharm 4 5 2 中使用 PyPy 作为标准 默认解释器 一切都在 Ubunutu 14 10 下运行 并且 pypy 已经安装 您可以在项目的设置下进行配置 这个官方文档直接涵盖了 https www jetbrains
  • 了解 Python 中的酸洗

    我最近接到一项作业 需要以腌制形式放置一本字典 其中每个键引用一个列表 唯一的问题是我不知道腌制形式是什么 谁能给我指出一些好的资源的正确方向来帮助我学习这个概念 pickle 模块实现了一个基本但强大的算法 用于序列化和反序列化 Pyth
  • 更新 Sqlalchemy 中的多个列

    我有一个在 Flask 上运行的应用程序 并使用 sqlalchemy 与数据库交互 我想用用户指定的值更新表的列 我正在使用的查询是 def update table value1 value2 value3 query update T
  • 查找模块中显式定义的函数 (python)

    好的 我知道您可以使用 dir 方法列出模块中的所有内容 但是有什么方法可以仅查看该模块中定义的函数吗 例如 假设我的模块如下所示 from datetime import date datetime def test return Thi
  • 当我在 Pandas 中使用 df.corr 时,我的一些列丢失了

    这是我的代码 import numpy as np import pandas as pd import seaborn as sns import matplotlib pyplot as plt data pd read csv dea
  • 如何使用 Django 项目设置 SQLite?

    我已阅读 Django 文档 仅供参考 https docs djangoproject com en 1 3 intro tutorial01 https docs djangoproject com en 1 3 intro tutor
  • Python多处理错误“ForkAwareLocal”对象没有属性“连接”

    下面是我的代码 我面临着多处理问题 我看到这个问题之前已经被问过 我已经尝试过这些解决方案 但它似乎不起作用 有人可以帮我吗 from multiprocessing import Pool Manager Class X def init
  • 具有屏蔽无效值的 pcolormesh

    我试图将一维数组绘制为 pcolormesh 因此颜色沿 x 轴变化 但每个 x 的 y 轴保持不变 但我的数据有一些错误值 因此我使用屏蔽数组和自定义颜色图 其中屏蔽值设置为蓝色 import numpy as np import mat
  • 使用 numpy 在 python 中执行最大方差旋转

    我正在研究矩阵的主成分分析 我已经找到了如下所示的组件矩阵 A np array 0 73465832 0 24819766 0 32045055 0 3728976 0 58628043 0 63433607 0 72617152 0 5
  • Python 声音(“铃声”)

    我想让一个 python 程序在完成任务时通过发出嘟嘟声来提醒我 目前 我使用import os然后使用命令行语音程序说 进程完成 我更愿意它是一个简单的 铃 我知道有一个函数可以用于Cocoa apps NSBeep 但我认为这与此没有太
  • Python]将两个文本文件合并为一个(逐行)[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我是蟒蛇新手 我想做的是将文件 a 和文件 b 逐行合并到一个文件中 例如 text file a a n b n c text fi
  • 如何将回溯/sys.exc_info() 值保存在变量中?

    我想将错误名称和回溯详细信息保存到变量中 这是我的尝试 import sys try try print x except Exception ex raise NameError except Exception er print 0 s
  • 对数据帧的每 2 小时数据进行 Groupby

    我有一个数据框 Time T201FN1ST2010 T201FN1VT2010 1791 2017 12 26 00 00 00 854 69 0 87 1792 2017 12 26 00 20 00 855 76 0 87 1793
  • 处理大文件的最快方法?

    我有多个 3 GB 制表符分隔文件 每个文件中有 2000 万行 所有行都必须独立处理 任何两行之间没有关系 我的问题是 什么会更快 逐行阅读 with open as infile for line in infile 将文件分块读入内存
  • 在 Django shell 会话期间获取 SQL 查询计数

    有没有办法打印 Django ORM 在 Django shell 会话期间执行的原始 SQL 查询的数量 Django 调试工具栏已经提供了此类信息 例如 5 QUERIES in 5 83MS但如何从 shell 中获取它并不明显 您可
  • 如何为所有用户安装 Anaconda python?

    Anaconda python 发行版 https store continuum io cshop anaconda 非常方便地部署科学计算环境 SCE 并根据需要切换python版本 默认情况下 安装会将 python 定位到 anac

随机推荐

  • JS浏览器调试:Browser对象

    好久不搞前端 最近在搞钉钉的第三方应用的时候 前端给我露了一手 涉及到知识主要是JavaScript的Browser对象 首先现在很多PC客户端现在技术选型选择会选择nodejs这类 像nw js或者Electron 都会涉及到chromi
  • 给input框赋值成功后input框不能进行编辑

    选中一项后 input框不能进行编辑
  • 【工具】(z-library平替)Clibrary中文图书馆,电子书大全

    目录 新版目录 更新于2023 7 11 一 更新时间和简介 二 步骤 老版目录 接口无法使用 1 z library和Clibrary简介 2 Clibrary网址 3 具体操作界面 新版目录 更新于2023 7 11 一 更新时间和简介
  • three.js 制作地球标注的两种方法

    一 Sprite精灵标签 效果图 精灵标签 标签永远面向相机 function createTxt position name var texture new THREE CanvasTexture getCanvasFont var fo
  • 自学——一个月入门前端④

    本文的内容有关css盒模型 盒模型 在css中 所有的元素都被一个个的 盒子 包围着 广泛的使用两种盒子 块级盒子和内联盒子 这两种盒子会在页面流和元素之间的关系 block 绝大部分情况下盒子会和父容器一样宽 每个盒子都会换行 width
  • C/C++判断指针是否为空

    if p NULL if NULL p if p nullptr if nullptr p if p 0 if 0 p if p false if false p if p 个人理解 如有不对 敬请指正 最佳判断是if p 因为 p是一个指
  • 02-分布式协调服务ZooKeeper

    目录 一 ZooKeeper简介 1 什么是Zookeeper 2 基本特性 二 ZooKeeper原理 1 系统架构 1 1 角色分工 1 2 设计思想 1 3 为什么要引入Observer ZK 3 3 0 2 数据模型 2 1 Zno
  • 花书+吴恩达深度学习(二六)近似推断(EM, 变分推断)

    文章目录 0 前言 1 将推断视为优化问题 1 1 期望最大化 EM 1 2 最大后验推断 MAP 1 3 稀疏编码 2 变分推断 2 1 离散型潜变量 2 2 连续性潜变量 如果这篇文章对你有一点小小的帮助 请给个关注 点个赞喔 我会非常
  • 【Redis】持久化之AOF

    Redis持久化之AOF 以日志的形式来记录每个写操作 增量保存 将Redis执行过的所有写指令记录下来 读操作不记录 只许追加文件但不可以改写文件 redis启动之初会读取该文件重新构建数据 换言之 redis 重启的话就根据日志文件的内
  • 【element】之el-popconfirm:弹出组件确认按钮绑定

    element之el popconfirm 弹出组件确认按钮绑定 一 element官网说明 element中el popconfirm实例 element提供的接口 二 实际代码说明 无用代码 正确代码 一 element官网说明 ele
  • 通过bilibili_api获取bilibili弹幕+绘制词云的方法!

    由于自己学艺不精 后续词云的简略代码没怎么看懂 梳理了一遍把整个的学习内容记录下来 主要参考的为bilibili api的教程和词云的生成教程 https blog csdn net itanders article details 888
  • 华为b6手环能升级鸿蒙吗,华为手环B6全新发布:跨界形态再升级 强劲性能革新穿戴体验...

    2020年7月30日 北京 今日 华为正式推出了融合耳机和手环形态的跨界穿戴智能手环华为手环B6 它采用1 53英寸高清3D弧面柔性屏 外观时尚 操控自如 独创的分离式设计 让这款产品兼具蓝牙耳机的舒适佩戴和华为智能手环的专业运动健康功能
  • [Ubuntu] [Qt] Ubuntu18.04.6安装Qt后打不开

    1 安装完Qt5 15 2后点击图标没反应 2 通过指令打开Qt 可以看到失败的原因是因为glibc 2 28没找到 Qt Tools QtCreator bin qtcreator software Qt Tools QtCreator
  • labelimg 修正模型错误标注遇到的问题

    场景介绍 使用了 模型 如YOLOv5 v7 detec py 保存的 YOLO 格式的结果 包括测试的图像和对应的 txt 文件 模型跑出来的结果可能不够准确 需要手工修正下 因此我需要使用 labelimg 来可视化图像 并且修改其标注
  • Tomcat安装版和解压版

    在eclipse中开发web项目经常需要在eclipse中添加tomcat服务器 之前下载了目前最新版本tomcat9的zip版 由于目前的eclipse只支持到tomcat8 原本准备就这样安装了 在浏览器输入了n次http localh
  • redis持久化操作RDB和AOF详解与操作(docker)

    redis持久化 Redis 提供了两种不同的持久化方法来将数据存储到硬盘里面 一种方法叫快照 snapshotting RDB 它可以将存在于某一时刻的所有数据都写入硬盘里面 另一种方法叫只追加文件 append only file AO
  • SVR4/4.3BSD与Linux对待伪终端的不同方式

    打开伪终端意味着打开了一个 终端对 这个终端对的其中一个是主终端 另一个是从终端 简单说主终端和类似sshd telnetd等用户空间的远程协议处理进程连接 而从终端则和shell之类的实际进程连接 在处理远程登录的时候 一般都是由远程协议
  • uniapp uview2 使用笔记

    创建项目安装组件 npm install uview ui 配置 引入uView主JS库 在项目src目录中的main js中 引入并使用uView的JS库 注意这两行要放在import Vue之后 main js import uView
  • 毕业设计-基于深度学习的肺炎医学 CT 图像分类算法研究

    目录 前言 课题背景和意义 实现技术思路 一 数据集及数据预处理 二 卷积神经网络 CNN 网络技术 三 分类模型结构与方法 三 基于改进的 Inception ResNet 的分类网络 实现效果图样例 最后 前言 大四是整个大学期间最忙碌
  • 解析网页-selenium-非常实用-python爬虫知识点7

    selenium 一 引入 二 配置Selenium chromdriver 三 Selenium的基本操作 一 设置驱动 退出驱动 driver webdriver Chrome 路径 driver quit 二 网页打开 关闭等基本操作