逆向爬虫12 selenium小进阶+案例
一、关于验证码
如何处理验证码:
1. 直接把浏览器里面的cookie拿出来直接用.
2. 手动编写验证码识别的功能(深度学习)
3. 第三方打码平台(收费), 超级鹰, 图鉴
除了超级鹰外,图鉴也是一个非常好用的第三方平台验证码识别工具,下面给出官方python代码示例:
1. 图鉴官方python代码示例
import base64
import json
import requests
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 开发者工具来观察加载顺序
- 下图是登录时的
HTTP请求头 信息,从中可以得知登录的 url链接 ,方法是 POST请求
- 下图是该POST请求所携带的参数,其中
captcha 是验证码,imgId 是验证码图片ID,两者如果匹配则允许登录,下面我们就要想方设法获取到这两个参数。
- 清掉抓包缓存内容,刷新下页面,获得下图,验证码刷新了,且重新发起了个
GET请求 ,猜测该请求是用来获取验证码图片的
- 进入响应预览中看到下图,果然是和图片相关,且包含
imgId参数 ,其中 img参数 就是验证码图像的 base64 编码字符串
因此使用 requests+图鉴 登录图鉴网站的步骤是:
- 使用
GET请求 获取到验证码图片信息,http://admin.ttshitu.com/captcha_v2 - 把验证码发送给图鉴,获得识别结果
- 把识别结果和
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():
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'],
"developerFlag": False,
"needCheck": True,
"password": "q6035945",
"userName": "q6035945",
}
login_url = "http://admin.ttshitu.com/common/api/login/user"
resp = session.post(login_url, 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)
cookie_dic = {dic['name']: dic['value'] for dic in cookies}
print(cookie_dic)
headers = {}
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直聘
在复现这个功能的时候,遇到了两个问题:
- 验证按钮的
xpath 是动态加载的,每次都是不一样的,因此在 F12工具 中需要复制 full xpath - 人机验证的方式有不止点选图片字符一种,还有一种是再点一次,因此验证阶段写了
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])
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(
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
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()
|