selenium

219 阅读6分钟

爬虫与反爬虫之间的斗争

图片.png

爬虫的建议

  • 尽量减少请求次数
    • 能抓取列表⻚就不抓详情⻚
    • 保存获取到的HTML,供查错和重复使⽤
  • 关注⽹站的所有类型的⻚⾯
    • H5页面
    • APP
  • 多伪装
    • 代理IP
    • 不适用cookie
  • 利用多线程分布式
    • 在不被禁的请求下尽可能的提高速度

动态HTML技术了解

  • JS

    • 是⽹络上最常⽤的脚本语⾔,它可以收集⽤户的跟踪数据,不需要重载⻚ ⾯直接提交表单,在⻚⾯嵌⼊多媒体⽂件,甚⾄运⾏⽹⻚
  • jQuery

    • jQuery是⼀个快速、简介的JavaScript框架,封装了JavaScript常⽤的 功能代码
  • ajax

    • ajax可以使⽤⽹⻚实现异步更新,可以在不重新加载整个⽹⻚的情况下,对⽹⻚的某部分进⾏更新

获取ajax数据的方式

  1. 直接分析ajax调⽤的接⼝。然后通过代码请求这个接⼝。
  2. 使⽤Selenium+chromedriver模拟浏览器⾏为获取数据
方式优点缺点
分析接口直接可以请求到数据.不需要做一下解析工作,代码量少,性能高分析接口比较复杂,特别是一些通过js混淆的接口,要有一定的js功底.容易被发现是爬虫
selenium直接模拟浏览器的行为.浏览器能请求到的,使用selenium也能请求到.爬虫更稳定代码量多,性能低

Selenium

selenium是⼀个web的⾃动化测试⼯具,最初是为⽹站⾃动化测试⽽开发的, selenium可以直接运⾏在浏览器上,它⽀持所有主流的浏览器,可以接收指 令,让浏览器⾃动加载⻚⾯,获取需要的数据,甚⾄⻚⾯截屏

chromedriver是⼀个驱动Chrome浏览器的驱动程序,使⽤他才可以驱动浏览器。当然针对不同的浏览器有不同的driver。以下列出了不同浏览器及其对应的driver:

Chrome: sites.google.com/a/chromium.…

chromedriver下载地址:
版本在114及以下:chromedriver.storage.googleapis.com/index.html
版本在127:googlechromelabs.github.io/chrome-for-…
其他版本下载方法:
如版本127.0.6533 32位下载地址是:

storage.googleapis.com/chrome-for-…

其他版本下载地址把上面地址中的版本号替换即可

两个地址都可以下载,根据自己的chrome浏览器的版本选择下载即可

若以上地址不可以,可以尝试: getwebdriver.com/


Firefox:github.com/mozilla/gec…

Edge:developer.microsoft.com/en-us/micro…

Safari:webkit.org/blog/6900/w…

因为我使用的是Anaconda环境,所以可以将下载好的压缩文件解压后复制chromedriver.exe到Anaconda安装目录下的Scripts目录下

图片.png

# -*- coding: UTF-8 -*-  
# @Project :网络爬虫  
# @File :selenium入门_01.py  
# @IDE :PyCharm  
# @Author :艳烔  
# @Date :2024/10/27 1:04  
  
from selenium import webdriver  
  
driver = webdriver.Chrome()  
  
driver.get("https://www.baidu.com")  
driver.implicitly_wait(20)  
print(driver.title)  
driver.close()

图片.png

图片.png

或者放到其他文件的目录下,如:D:\Development\

图片.png

这种方式需要自己在Python程序中指定安装目录

安装Selenium

pip install selenium

图片.png

Selenium入门

Chrome 浏览器提供了无头模式(headless mode),可以在不打开图形界面的情况下运行浏览器。你可以使用 ChromeDriver 并配置 Chrome 为无头模式。

# -*- coding: UTF-8 -*-  
# @Project :网络爬虫  
# @File :Phantomjs案例.py  
# @IDE :PyCharm  
# @Author :艳烔  
# @Date :2024/10/27 9:04  
  
from selenium import webdriver  
from selenium.webdriver.chrome.options import Options  
from time import sleep  
from selenium.webdriver.common.by import By  
  
# 设置Chrome为无头模式  
chrome_options = Options()  
chrome_options.add_argument('--headless')  
  
# 创建ChromeDriver实例  
driver = webdriver.Chrome(chrome_options)  
driver.get("https://www.baidu.com")  
print(driver.title)  
  
driver.implicitly_wait(4)  
# 定位和操作  
driver.find_element('id', 'kw').send_keys('长城')  
driver.find_element(By.ID, 'su').click()  
  
driver.implicitly_wait(4)  
# 查看请求信息  
print(driver.page_source) # 查看网页源码  
print(driver.get_cookies()) # 查看cookies  
print(driver.current_url) # 查看当前页面的url  
  
driver.quit() # 退出浏览器

参考文档:www.runoob.com/python3/pyt…

www.selenium.dev/zh-cn/

要注意, find_element 是获取第⼀个满⾜条件的元素。 find_elements 是获取所有满⾜条件的元素。

操作按钮:操作按钮有很多种⽅式。⽐如单击、右击、双击等。点击,直接调⽤click函数就可以了。

click_and_hold(element):点击但不松开⿏标。

context_click(element):右键点击。

double_click(element):双击。

更多⽅法请参考:selenium-python.readthedocs.io/api.html

# -*- coding: UTF-8 -*-  
# @Project :网络爬虫  
# @File :登录豆瓣练习_03.py  
# @IDE :PyCharm  
# @Author :艳烔  
# @Date :2024/10/27 9:39  
  
from selenium import webdriver  
from selenium.webdriver.common.by import By  
from selenium.webdriver.chrome.options import Options  
from time import sleep  
  
# 无界面模式  
chrome_options = Options()  
chrome_options.add_argument('--headless')  
# 打开豆瓣  
driver = webdriver.Chrome()  
driver.get("https://www.douban.com/")  
driver.implicitly_wait(3)  
login_frame = driver.find_element(By.XPATH, '//div[@class="login"]/iframe')  
# 切换到登录页面  
driver.switch_to.frame(login_frame)  
driver.find_element(By.CLASS_NAME, 'account-tab-account').click()  
  
driver.find_element(By.ID, 'username').send_keys('15663254155')  
driver.find_element(By.ID, 'password').send_keys('123456')  
driver.find_element(By.XPATH, '/html/body/div[1]/div[2]/div[1]/div[5]').click()  
sleep(3)  
  
# 后面需要滑块验证  
driver.quit()

行为链

有时候在⻚⾯中的操作可能要有很多步,那么这时候可以使⽤⿏标⾏为链类 ActionChains来完成。⽐如现在要将⿏标移动到某个元素上并执⾏点击事件。

# -*- coding: UTF-8 -*-  
# @Project :网络爬虫  
# @File :行为链.py  
# @IDE :PyCharm  
# @Author :艳烔  
# @Date :2024/10/27 10:14  
import time  
  
from selenium import webdriver  
from selenium.webdriver.common.by import By  
from selenium.webdriver.common.action_chains import ActionChains  
  
driver = webdriver.Chrome()  
driver.get('https://www.baidu.com')  
  
inputTag = driver.find_element(By.ID,'kw')  
subBtn = driver.find_element(By.ID,'su')  
  
action = ActionChains(driver)  
action.move_to_element(inputTag)  
action.send_keys_to_element(inputTag,'python')  
action.move_to_element(subBtn)  
action.context_click() # 右键  
action.click(subBtn)  
# 提交行为链上的操作  
action.perform()

Cookie操作

# -*- coding: UTF-8 -*-  
# @Project :网络爬虫  
# @File :Cookie操作.py  
# @IDE :PyCharm  
# @Author :艳烔  
# @Date :2024/10/27 10:33  
  
from selenium import webdriver  
from selenium.webdriver.common.by import By  
  
driver = webdriver.Chrome()  
driver.get('https://www.douban.com')  
  
# 获取所有的cookie  
cookies = driver.get_cookies()  
for cookie in cookies:  
print(cookie)  
  
print("==="*30)  
# 根据cookie的name获取cookie的值  
print(driver.get_cookie('ll'))  
  
print("==="*30)  
# 删除cookie  
driver.delete_cookie('ll')  
  
print(driver.get_cookie('ll'))  
  
  
driver.quit()

页面等待

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

  • 隐式等待:调⽤driver.implicitly_wait。那么在获取不可⽤的元素之前,会先等待10秒中的时间。
  • 显示等待:显示等待是表明某个条件成⽴后才执⾏获取元素的操作。也可以在等待的时候指定⼀个最⼤的时间,如果超过这个时间那么就抛出⼀个异常。显示等待应该使⽤ selenium.webdriver.support.excepted_conditions期望的条件和 selenium.webdriver.support.ui.WebDriverWait来配合完成。
# -*- coding: UTF-8 -*-
#    @Project :网络爬虫 
#    @File    :页面等待.py
#    @IDE     :PyCharm 
#    @Author  :艳烔
#    @Date    :2024/10/27 10:45

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:
    WebDriverWait(driver, 10).until(
        EC.presence_of_element_located(
            (By.ID, 'kwss')
        )
    )
finally:
    driver.quit()

⼀些其他的等待条件

  • presence_of_element_located:某个元素已经加载完毕了。
  • presence_of_all_elements_located:⽹⻚中所有满⾜条件的元素都加载完毕了。
  • element_to_be_clickable:某个元素是可以点击了。

更多条件请参考:selenium-python.readthedocs.io/waits.html

打开多窗口和切换页面

有时候窗⼝中有很多⼦tab⻚⾯。这时候肯定是需要进⾏切换的。selenium提供 了⼀个叫做switch_to_window来进⾏切换,具体切换到哪个⻚⾯,可以从driver.window_handles中找到。

# -*- coding: UTF-8 -*-  
# @Project :网络爬虫  
# @File :打开多窗口.py  
# @IDE :PyCharm  
# @Author :艳烔  
# @Date :2024/10/31 8:01  
import time  
  
from selenium import webdriver  
from selenium.webdriver.common.by import By  
  
driver = webdriver.Chrome()  
driver.get("https://www.baidu.com")  
  
driver.execute_script("window.open('https://www.douban.com')")  
  
driver.find_element(By.ID, 'kw').send_keys("python")  
  
print(driver.current_url)  
  
# 切换界面  
driver.switch_to.window(driver.window_handles[0])  
print(driver.current_url)  
time.sleep(10)  
# driver.close()  
  
# driver.quit()

模拟QQ邮箱登录

# -*- coding: UTF-8 -*-  
# @Project :网络爬虫  
# @File :模拟登录QQ邮箱.py  
# @IDE :PyCharm  
# @Author :艳烔  
# @Date :2024/10/31 8:11  
import time  
  
from selenium import webdriver  
from selenium.webdriver.common.by import By  
  
driver = webdriver.Chrome()  
driver.implicitly_wait(10)  
driver.get('https://wx.mail.qq.com/')  
  
login_from_1 = driver.find_element(By.CLASS_NAME, 'QQMailSdkTool_login_loginBox_qq_iframe')  
driver.switch_to.frame(login_from_1)  
  
login_from_2 = driver.find_element(By.ID, 'ptlogin_iframe')  
driver.switch_to.frame(login_from_2)  
  
# 点击 密码登录 按钮  
driver.find_element(By.ID, 'switcher_plogin').click()  
  
# 发送账号密码  
driver.find_element(By.ID, 'u').send_keys('5636816663')  
driver.find_element(By.ID, 'p').send_keys('123456')  
  
# 点击登录按钮  
driver.find_element(By.ID, 'login_button').click()  
  
# 后面需要进行安全验证  
time.sleep(3)