逆向爬虫12 selenium小进阶+案例

2023-10-27

逆向爬虫12 selenium小进阶+案例

一、关于验证码

如何处理验证码:

1. 直接把浏览器里面的cookie拿出来直接用. 
2. 手动编写验证码识别的功能(深度学习)
3. 第三方打码平台(收费), 超级鹰, 图鉴

除了超级鹰外,图鉴也是一个非常好用的第三方平台验证码识别工具,下面给出官方python代码示例:

1. 图鉴官方python代码示例

import base64
import json
import requests
# 一、图片文字类型(默认 3 数英混合):
# 1 : 纯数字
# 1001:纯数字2
# 2 : 纯英文
# 1002:纯英文2
# 3 : 数英混合
# 1003:数英混合2
#  4 : 闪动GIF
# 7 : 无感学习(独家)
# 11 : 计算题
# 1005:  快速计算题
# 16 : 汉字
# 32 : 通用文字识别(证件、单据)
# 66:  问答题
# 49 :recaptcha图片识别
# 二、图片旋转角度类型:
# 29 :  旋转类型
#
# 三、图片坐标点选类型:
# 19 :  1个坐标
# 20 :  3个坐标
# 21 :  3 ~ 5个坐标
# 22 :  5 ~ 8个坐标
# 27 :  1 ~ 4个坐标
# 48 : 轨迹类型
#
# 四、缺口识别
# 18 : 缺口识别(需要2张图 一张目标图一张缺口图)
# 33 : 单缺口识别(返回X轴坐标 只需要1张图)
# 五、拼图识别
# 53:拼图识别
def base64_api(uname, pwd, img, typeid):
    with open(img, 'rb') as f:
        base64_data = base64.b64encode(f.read())
        b64 = base64_data.decode()
    data = {"username": uname, "password": pwd, "typeid": typeid, "image": b64}
    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]
    return ""

if __name__ == "__main__":
    img_path = "C:/Users/Administrator/Desktop/file.jpg"	# 换成你要识别的验证码图片
    result = base64_api(uname='你的账号', pwd='你的密码', img=img_path, typeid=3)	# 换成你的账号和密码
    print(result)

2. 使用图鉴登录图鉴

之前用 selenium+超级鹰 成功解决了超级鹰的登录,这里使用 requests+图鉴 来解决图鉴的登录

使用 requests模块 就必须抓包了解网页的加载请求过程,这里我们先认为进行一次登录,通过 F12 开发者工具来观察加载顺序

  1. 下图是登录时的 HTTP请求头 信息,从中可以得知登录的 url链接 ,方法是 POST请求

在这里插入图片描述

  1. 下图是该POST请求所携带的参数,其中 captcha 是验证码,imgId 是验证码图片ID,两者如果匹配则允许登录,下面我们就要想方设法获取到这两个参数。

在这里插入图片描述

  1. 清掉抓包缓存内容,刷新下页面,获得下图,验证码刷新了,且重新发起了个 GET请求 ,猜测该请求是用来获取验证码图片的

在这里插入图片描述

  1. 进入响应预览中看到下图,果然是和图片相关,且包含 imgId参数,其中 img参数 就是验证码图像的 base64 编码字符串

在这里插入图片描述

因此使用 requests+图鉴 登录图鉴网站的步骤是:

  1. 使用 GET请求 获取到验证码图片信息,http://admin.ttshitu.com/captcha_v2
  2. 把验证码发送给图鉴,获得识别结果
  3. 把识别结果和 imgId 填入 POST请求 参数中,并登录,http://admin.ttshitu.com/common/api/login/user
"""
	1. 使用GET请求获取到验证码图片信息,http://admin.ttshitu.com/captcha_v2
	2. 把验证码发送给图鉴,获得识别结果
	3. 把识别结果和imgId填入POST请求参数中,并登录,http://admin.ttshitu.com/common/api/login/user
"""
import requests
import json

def base64_api(uname, pwd, img, typeid):
    data = {"username": uname, "password": pwd, "typeid": typeid, "image": img}
    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]
    return ""

def login():
    # 请求到图片的地址,提取到图片的b64以及图片的imgId
    verify_url = "http://admin.ttshitu.com/captcha_v2"
    session = requests.session()
    resp = session.get(verify_url)
    img = resp.json()
    result = base64_api(uname='q6035945', pwd='q6035945', img=img['img'], typeid=3)

    data = {
        "captcha": result,             # 验证码
        "imgId": img['imgId'],         # 通过抓包获取imgId
        "developerFlag": False,
        "needCheck": True,
        "password": "xxxxxx",
        "userName": "xxxxxx",
    }
    login_url = "http://admin.ttshitu.com/common/api/login/user"    # 登录url
    resp = session.post(login_url, json=data)   # 这里不是data=data,是json=data
    print(resp.text)

if __name__ == "__main__":
    login()

3. selenium如何获取cookies

from selenium.webdriver import Chrome
import requests

web = Chrome()
web.get("http://www.baidu.com")

cookies = web.get_cookies()
print(cookies)  # cookies中只有name和value有用

# cookie_dic = {}
# for dic in cookies:
#     key = dic['name']
#     value = dic['value']
#     cookie_dic[key] = value
cookie_dic = {dic['name']: dic['value'] for dic in cookies}  # 字典生成式代替上面5行内容
print(cookie_dic)

# 当你已经有了一个字典形式的cookie,可以直接把这个字典作为参数传递个requests
headers = {}								   # 直接把cookies当成参数传递即可(必须是字典)
requests.get("http://www.baidu.com", headers=headers, cookies=cookie_dic)  

二、关于等待

在selenium中有三种等待方案

1. time.sleep()

这个没啥说的,就是干等。不论元素是否加载出来,都要等

2. web.implicitly_wait()

这个比上面那个人性化很多。如果元素加载出来了。就继续,如果没加载出来,此时会等待一段时间。

注意,此设置是全局设置。一次设置后,后面的加载过程都按照这个来。(爬虫用的会多一些)

3. WebDriverWait()

这个比较狠,单独等一个xxxx元素,如果出现了。就过,如果不出现。超时后, 直接报错。

# 显示等待
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By   # 提取页面内容的
from selenium.webdriver.support import expected_conditions as EC

ele = WebDriverWait(web, 10, 0.5).until(
    EC.presence_of_element_located((By.XPATH, "/html/body/div[5]/div[2]/div[1]/div/div"))
)

三、登录Boss直聘

在复现这个功能的时候,遇到了两个问题:

  1. 验证按钮的 xpath 是动态加载的,每次都是不一样的,因此在 F12工具 中需要复制 full xpath
  2. 人机验证的方式有不止点选图片字符一种,还有一种是再点一次,因此验证阶段写了 try 捕获异常
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
import time
import requests
import json
# 事件链
from selenium.webdriver.common.action_chains import ActionChains

def base64_api(uname, pwd, img, typeid):
    data = {"username": uname, "password": pwd, "typeid": typeid, "image": img}
    result = json.loads(requests.post("http://api.ttshitu.com/predict", json=data).text)
    if result['success']:
        return result["data"]["result"]
    else:
        return result["message"]
    return ""

web = Chrome()
web.implicitly_wait(3)
web.get("https://login.zhipin.com/?ka=header-login")
web.find_element(By.XPATH, '//*[@id="wrap"]/div[2]/div[3]/div[2]/div[2]').click()   # 切换到手机密码登录
web.find_element(By.XPATH, '//*[@id="wrap"]/div[2]/div[1]/div[2]/div[1]/form/div[3]/span[2]/input').send_keys('123456789')  # 输入手机号
web.find_element(By.XPATH, '//*[@id="wrap"]/div[2]/div[1]/div[2]/div[1]/form/div[4]/span/input').send_keys('123456789')     # 输入密码
web.find_element(By.XPATH, '/html/body/div[1]/div[2]/div[1]/div[2]/div[1]/form/div[5]/div[1]/div').click()    # 点击人机验证按钮

time.sleep(2)
try:
    # 常规验证方式,点选图片中的文字
    verify_div = web.find_element(By.XPATH, '/html/body/div[5]/div[2]/div[1]/div/div')
    verify_div.screenshot('tu.png')
    tu = verify_div.screenshot_as_base64
    result = base64_api(uname='q6035945', pwd='q6035945', img=tu, typeid=27)
    for p in result.split("|"):
        x = int(p.split(",")[0])
        y = int(p.split(",")[1])                                                              # perform(): 提交事件
        ActionChains(web).move_to_element_with_offset(verify_div, xoffset=x, yoffset=y).click().perform()
        time.sleep(1)
    web.find_element(By.XPATH, '/html/body/div[5]/div[2]/div[1]/div/div/div[3]/a/div').click()
except Exception as e:
    # 另一种验证方式,再点一次验证按钮
    web.find_element(By.XPATH, '/html/body/div[1]/div[2]/div[1]/div[2]/div[1]/form/div[5]/div[1]/div/div[1]/div[1]/span').click()
finally:
    # 完成验证后点击登录
    time.sleep(2)
    web.find_element(By.XPATH, '/html/body/div[1]/div[2]/div[1]/div[2]/div[1]/form/div[6]/button').click()

四、用selenium+lxml完成数据抓取

利用selenium 访问网页获取到网页 html 代码,再利用 lxml 解析得到指定内容。

from selenium.webdriver import Chrome
# 显示等待
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.common.by import By   # 提取页面内容的
from selenium.webdriver.support import expected_conditions as EC
from lxml import etree

def get_page_source(url):
    web.get(url)
    el = WebDriverWait(web, 10, 0.5).until(     # until  结束等待的条件
        EC.presence_of_element_located((By.XPATH, '/html/body/div[1]/div[3]/div/div[3]/ul/li[1]/div/div[1]/div[1]/div/div[1]/span[1]/a'))
    )
    page_source = web.page_source
    web.quit()
    return page_source

def get_job_name(page_source):
    tree = etree.HTML(page_source)
    job_names = tree.xpath('/html/body/div[1]/div[3]/div/div[3]/ul/li/div/div[1]/div[1]/div/div[1]/span[1]/a/text()')
    print(job_names)

if __name__ == "__main__":
    web = Chrome()
    url = "https://www.zhipin.com/job_detail/?query=python&city=101020100&industry=&position="
    page_source = get_page_source(url)
    get_job_name(page_source)

五、登录12306

复现这个功能的时候遇到以下问题:12306的验证码功能消失了,代码变简单了

from selenium.webdriver.chrome.options import Options
from selenium.webdriver import Chrome
from selenium.webdriver.common.by import By
import time
from selenium.webdriver.common.action_chains import ActionChains

# 如果你的浏览器版本是88以前, 要去执行一段js代码
# web.execute_cdp_cmd("Page.addScriptToEvaluateOnNewDocument", {
#   "source": """
#   navigator.webdriver = undefined
#     Object.defineProperty(navigator, 'webdriver', {
#       get: () => undefined
#     })
#   """
# })

# 88以后的版本用下面的方案
opt = Options()
opt.add_argument("--disable-blink-features=AutomationControlled")

web = Chrome(options=opt)
web.get("https://kyfw.12306.cn/otn/resources/login.html")

web.implicitly_wait(5)

web.find_element(By.XPATH, '/html/body/div[1]/div[2]/div[2]/div[1]/div[1]/div[1]/input').send_keys("12345678901")
web.find_element(By.XPATH, '/html/body/div[1]/div[2]/div[2]/div[1]/div[1]/div[2]/input').send_keys("1234567890")
web.find_element(By.XPATH, '/html/body/div[1]/div[2]/div[2]/div[1]/div[1]/div[4]/a').click()
time.sleep(1)
btn = web.find_element(By.XPATH, '/html/body/div[1]/div[4]/div[2]/div[2]/div/div/div[2]/div/div[1]/span')
ActionChains(web).drag_and_drop_by_offset(btn, xoffset=300, yoffset=0).perform()
# ActionChains(web).click_and_hold().move_by_offset()
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

逆向爬虫12 selenium小进阶+案例 的相关文章

  • SQLAlchemy 通过关联对象声明式多对多自连接

    我有一个用户表和一个朋友表 它将用户映射到其他用户 因为每个用户可以有很多朋友 这个关系显然是对称的 如果用户A是用户B的朋友 那么用户B也是用户A的朋友 我只存储这个关系一次 除了两个用户 ID 之外 Friends 表还有其他字段 因此
  • 将 Matplotlib 误差线放置在不位于条形中心的位置

    我正在 Matplotlib 中生成带有错误栏的堆积条形图 不幸的是 某些层相对较小且数据多样 因此多个层的错误条可能重叠 从而使它们难以或无法读取 Example 有没有办法设置每个误差条的位置 即沿 x 轴移动它 以便重叠的线显示在彼此
  • 通过最小元素比较对 5 个元素进行排序

    我必须在 python 中使用元素之间的最小比较次数来建模对 5 个元素的列表进行排序的执行计划 除此之外 复杂性是无关紧要的 结果是一个对的列表 表示在另一时间对列表进行排序所需的比较 我知道有一种算法可以通过 7 次比较 总是在元素之间
  • 从字符串中删除识别的日期

    作为输入 我有几个包含不同格式日期的字符串 例如 彼得在16 45 我的生日是1990年7月8日 On 7 月 11 日星期六我会回家 I use dateutil parser parse识别字符串中的日期 在下一步中 我想从字符串中删除
  • 如何在 Python 中检索 for 循环中的剩余项目?

    我有一个简单的 for 循环迭代项目列表 在某些时候 我知道它会破裂 我该如何退回剩余的物品 for i in a b c d e f g try some func i except return remaining items if s
  • PyUSB 1.0:NotImplementedError:此平台不支持或未实现操作

    我刚刚开始使用 pyusb 基本上我正在玩示例代码here https github com walac pyusb blob master docs tutorial rst 我使用的是 Windows 7 64 位 并从以下地址下载 z
  • 以编程方式停止Python脚本的执行? [复制]

    这个问题在这里已经有答案了 是否可以使用命令在任意行停止执行 python 脚本 Like some code quit quit at this point some more code that s not executed sys e
  • OpenCV 无法从 MacBook Pro iSight 捕获

    几天后 我无法再从 opencv 应用程序内部打开我的 iSight 相机 cap cv2 VideoCapture 0 返回 并且cap isOpened 回报true 然而 cap grab 刚刚返回false 有任何想法吗 示例代码
  • AWS EMR Spark Python 日志记录

    我正在 AWS EMR 上运行一个非常简单的 Spark 作业 但似乎无法从我的脚本中获取任何日志输出 我尝试过打印到 stderr from pyspark import SparkContext import sys if name m
  • 如何在ipywidget按钮中显示全文?

    我正在创建一个ipywidget带有一些文本的按钮 但按钮中未显示全文 我使用的代码如下 import ipywidgets as widgets from IPython display import display button wid
  • IO 密集型任务中的 Python 多线程

    建议仅在 IO 密集型任务中使用 Python 多线程 因为 Python 有一个全局解释器锁 GIL 只允许一个线程持有 Python 解释器的控制权 然而 多线程对于 IO 密集型操作有意义吗 https stackoverflow c
  • Pandas:merge_asof() 对多行求和/不重复

    我正在处理两个数据集 每个数据集具有不同的关联日期 我想合并它们 但因为日期不完全匹配 我相信merge asof 是最好的方法 然而 有两件事发生merge asof 不理想的 数字重复 数字丢失 以下代码是一个示例 df a pd Da
  • 向 Altair 图表添加背景实心填充

    I like Altair a lot for making graphs in Python As a tribute I wanted to regenerate the Economist graph s in Mistakes we
  • 每个 X 具有多个 Y 值的 Python 散点图

    我正在尝试使用 Python 创建一个散点图 其中包含两个 X 类别 cat1 cat2 每个类别都有多个 Y 值 如果每个 X 值的 Y 值的数量相同 我可以使用以下代码使其工作 import numpy as np import mat
  • 对年龄列进行分组/分类

    我有一个数据框说df有一个柱子 Ages gt gt gt df Age 0 22 1 38 2 26 3 35 4 35 5 1 6 54 我想对这个年龄段进行分组并创建一个像这样的新专栏 If age gt 0 age lt 2 the
  • 有没有办法检测正在运行的代码是否正在上下文管理器内执行?

    正如标题所述 有没有办法做到这样的事情 def call back if called inside context print running in context else print called outside context 这将
  • 有人用过 Dabo 做过中型项目吗? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我们正处于一个新的 ERP 风格的客户端 服务器应用程序的开始阶段 该应用程序是作为 Python 富客户端开发的 我们目前正在评估 Dabo
  • 如何为基于 Polymer (JS) 的应用程序编写端到端测试(大约 2015 年 5 月)?

    我已经构建了一个基于聚合物的应用程序 我想为其编写一些端到端测试 不是单元测试 而是用户行为集成测试 目前 2015 年 5 月 我该如何执行此操作 这几天我一直在研究这个问题 尽管网络上有大量专门讨论一个或另一个相关主题的页面 但没有任何
  • Python Selenium:如何在文本文件中打印网站上的值?

    我正在尝试编写一个脚本 该脚本将从 tulsaspca org 网站获取以下 6 个值并将其打印在 txt 文件中 最终输出应该是 905 4896 7105 23194 1004 42000 放置的动物 的 HTML span class
  • Statsmodels.formula.api OLS不显示截距的统计值

    我正在运行以下源代码 import statsmodels formula api as sm Add one column of ones for the intercept term X np append arr np ones 50

随机推荐

  • 查看linux jvm使用情况,查看jvm内存使用命令

    jmap linux下特有 也是很经常使用的一个命令 java 观察运行中的jvm物理内存的占用状况 linux 参数以下 数据库 heap 打印jvm heap的状况 histo 打印jvm heap的直方图 其输出信息包括类名 对象数量
  • oracle提示 o s-error,【案例】Oracle报错OSD-04016 O/S-Error 使用dd复制数据块恢复数据...

    天萃荷净 运维DBA反映数据库在异常断电导致硬盘IO出现O S Error OS 23 数据错误 循环冗余检查 错误 分析原因为坏块导致 通过dd来复制数据块修复数据库 一台数据库因为异常断电导致硬盘IO出现O S Error OS 23
  • 在vue项目引入天地图,根据经纬度获取具体地址

    1 申请key 天地图地图服务对所有用户开放 使用本组服务之前 需要申请Key 2 引入API 地图API是由JavaScript语言编写的 您在使用之前需要通过
  • OpenCV——双边滤波

    目录 一 双边滤波 二 C 代码 三 python代码 四 结果展示 一 双边滤波 双边滤波是一种综合考虑滤波器内图像空域信息和滤波器内图像像素灰度值相似性的滤波算法 可以实现在保留区域信息的基础上实现对噪声的去除 对局部边缘的平滑 双边滤
  • 神码ai伪原创【php源码】

    大家好 小编为大家解答python必备常用英语词汇笔记的问题 很多人还不知道python中常用的英语单词 现在让我们一起来看看吧 火车头采集ai伪原创插件截图 一 什么是注释 注释是对一段代码的解释 不参与程序运行 起到提示作用 教我pyt
  • Windows注册表互换Caps Lock、Shift、Ctr l键

    按键映射 在注册表找到 HKEY LOCAL MACHINE SYSTEM CurrentControlSet Control Keyboard Layout 下如果没有Scancode Map就新建一个二进制值项名为Scancode Ma
  • 有了这两本书,学习领域驱动设计会很容易

    自2003年Eric Evans的著作 领域驱动设计 面世以来 领域驱动设计 DDD 相关的实践书籍并不多 整体的理论发展速度并不快 以至于很长一段时间 开发团队的实践过程总是磕磕绊绊 这让他们觉得领域驱动设计的门槛很高 甚至有人怀疑领域驱
  • Linux——fork进程复制,fork的写时拷贝技术

    前言 进程是一个运行中的程序 每个进程都有一个进程控制块 英文缩写PCB Linux系统中的进程控制块是一个结构体strut task struct实现 PCB是进程存在的唯一标志 数据结构中定义的内容是为后面的管理提供支持的 所以不同的操
  • 记录promise解决js与oc交互中异步回调的实践

    项目需求 更改h5与客户端 安卓 ios交互 的交互方法 使用第三方jsBridge 因为使用了js来定义方法 oc调用的模式 大坑 导致兼容 页面刷新 客户端外调用等情况 难以解决 因为需要 在交互方法之后进行判断 从而执行回调 而交互无
  • 越早加入刷脸支付将享受越多的政策

    刷脸支付已成为2019支付生态的风口 对于超市 便利店 企事业单位 停车场 餐厅等所有支付场景 越早加入刷脸支付 将享受越多的风口红利 现在 牵手掌优科技 便能快速接入刷脸支付 开拓全国刷脸支付市场 瓜分更多支付红利 支付宝 蜻蜓 采用了3
  • iOS 8 and iPhone 6 for web developers and designers: next evolution for Safari and native webapps

    本文原文为 iOS 8 and iPhone 6 for web developers and designers next evolution for Safari and native webapps 译者 罗罗磊磊 转载请注明 喜大普
  • python typeerror总结_错误总结

    1 TypeError The value of a feed cannot be a tf Tensor object Acceptable feed values include Python scalars strings lists
  • C++ 面试资料总结(全)

    C interview 总结了下C 相关的基础知识用于面试 大部分内容从网上搜罗而来 侵删 有些内容是根据自己理解写的 如有错误请指出哦 const 修饰变量 说明该变量不能被改变 修饰指针 分为指向常量的指针和指针常量 指向常量的指针值指
  • 考研复试数据库原理课后习题(十一)——并发控制

    并发控制 1 数据库中为什么要并发控制 并发控制能保证事务的哪些特性 数据库是共享资源 通常有多个事务同时在运行 当多个事务并发地存取数据库时就会产生读取和 或修改同一数据的情况 若对并发操作不加控制就可能会存取和存储不正确的数据 破坏数据
  • win7 easybcd 安装centos7.5 双系统

    之前用easybcd安装过Ubuntu 比较简单 腾出一些空间 添加引导项 然后就可以想安装普通的操作系统一样安装了 安装完之后 可以修改grub 让其可以同时引导Linux和Windows 这样就装好了 但是安装centos7有些地方不一
  • 12_MySQL之DCL语言

    文章目录 1 概述 2 用户管理 2 1 添加用户 2 2 删除用户 2 3 修改用户密码 2 4 查询用户 3 权限管理 3 1 查询权限 3 2 授予权限 3 3 取消权限 1 概述 DCL是数据库控制语言 用于执行权限的授予和收回操作
  • Unity的C#编程教程_34_for循环语句挑战2数苹果

    使用协同程序 协程 Coroutine 来分解循环程序 设计一个数苹果的程序 每隔1秒数一次 using System Collections using System Collections Generic using UnityEngi
  • 影院管理系统!个人做的,还有不完整的地方,源码我奉献了吧!

    影院管理系统 个人做的 还有不完整的地方 源码我奉献了吧 下载地址 http download csdn net detail liangrui1988 5753387
  • iOS 导航栏设置

    导航栏右侧的Done按钮怎么是蓝色的 导航栏右侧按钮大小设置 导航栏标题按钮样式设置 导航栏设置颜色 导航栏变白不显示颜色 iOS 13 之后使用新的API和类 UINavigationBarAppearance 来设置导航栏的标题大小 颜
  • 逆向爬虫12 selenium小进阶+案例

    逆向爬虫12 selenium小进阶 案例 一 关于验证码 如何处理验证码 1 直接把浏览器里面的cookie拿出来直接用 2 手动编写验证码识别的功能 深度学习 3 第三方打码平台 收费 超级鹰 图鉴 除了超级鹰外 图鉴也是一个非常好用的