自动登陆并获取订单信息

背景

朋友做的是集成商的生意,他碰到一个问题希望我能解决下,提升一下他的工作效率。

朋友接了一个小区xx改造订单,这个订单的原件都从A公司采购,由于原件很多,所以在A公司里面就会有很多订单号,里面有一些关键信息,比如”价格”,也有一些不敏感信息比如”快递信息”等等。朋友碰到两个问题:

  • 不需要自己的员工查看到敏感信息,但又必须让他们知道快递等一些信息 。

    1
    现在比较简单,就是通过中间“商务”这个人来做,工作就很繁杂
  • 小区xx改造完工时,该订单对账太繁琐,毛利等利润计算工作巨大

朋友的想法,是希望能够把A公司的订单信息能够自动纳入到他们的数据库中,这样朋友只要维护好xx小区的订单号下面涉及哪些A公司订单就可以了, 剩下的就简单很多了。

方案

一开始想法,就是A公司能否提供一个开放api接口给朋友调用,那么就可以获取到订单信息了,但A公司没有这个功能。

那剩下的想法就是爬虫了。

试试看

分析过程

大概估计了一下会遇到的困难

  • 自动填充数据

  • 自动填充校验码

  • 爬虫订单数据

爬虫订单数据

通过chrome的页面调试功能,抓包分析了页面的一些结构和https请求,获取订单信息API包含如下三个关键信息

  • url (已知)

  • cookies

  • post body (已知)

并分析了他们页面登陆时密码的机密规则: 公钥+密码+校验码, 本想能否跳过自动登陆,直接获取订单信息看来是不行了。

cookies

我使用的chrome 81.x的,所以主要是已这个版本举例。

  • 使用sqllite 工具打开cookies文件 “%LOCALAPPDATA%\Google\Chrome\User Data\Default” 里面是加密的

  • 查询资料 “http://www.secwk.com/2020/03/09/16685/" ,了解加密规则

  • 资料中提供的demo 可以解密出cookies的值

爬虫部分基本解决了,只要能够登陆成功,我就可以通过工具获取cookies,然后通过构造api请求正确的订单数据

自动填充校验码

A公司的验证码不复杂,难度也不大,只要能获取到图片就能识别出数字。

自己搭了一个测试页面,上传图片就可以识别。

测试链接

自动填充数据

本来是想用libcef 自己写一个类似的web客户端,发现cookies获取成本太高;接着查询资料使用 selenium 来实现,开发语言用python。

1
注意:请选择安装正确版本的chrome driver,并将chromedriver.exe 的路径设置到 环境变量PATH中。

随着分析的深入,发现A公司的验证码其实不是一张图片,而是通过api向服务器获取返回一个字符串,其实就是不需要验证码识别的,只要获取element并填回去就好了。

1
2
3
4
5
# 设置校验码
txtOCR = driver.find_element(By.ID,'ocr').get_attribute('value')

inputOCR = driver.find_element(By.ID,'code')
inputOCR.send_keys(txtOCR)

selenium 还可以获取当前域解密后的cookies,那整体比我原来想象的简单多了。

所以最后的代码就是这样:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# -*- coding: UTF-8 -*-

import time
import requests
import json
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.common.keys import Keys
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support.expected_conditions import presence_of_element_located

driver = webdriver.Chrome()

# Navigate to url
driver.get("https://xxxxx.com/")


# 选择账号密码登陆
btnloginbyuserid = driver.find_element(By.CLASS_NAME,'userId')
btnloginbyuserid.click()

# 设置账号、密码
txtUser = driver.find_element(By.ID,'userID')
txtpwd = driver.find_element(By.ID,'Pwd')

txtUser.send_keys('xxx')
txtpwd.send_keys('ppp')

# 设置校验码
txtOCR = driver.find_element(By.ID,'ocr').get_attribute('value')

inputOCR = driver.find_element(By.ID,'code')
inputOCR.send_keys(txtOCR)

# 点击登陆
btnLogon = driver.find_element(By.ID,'btn_login')
btnLogon.click()

# 等待10s
time.sleep( 10 )

# Get all available cookies
print driver.get_cookies()

# 构造 api消息

postheaders={'Cookie': 'sui bian xie de'}
postdata={'begin':'2019-02-11','end':'2019-05-11'}
r = requests.post('https://xxxxx.com/Getlist', headers=postheaders, data=postdata)

# 请求失败
if r.status_code == 200:
print(r.text)
else:
print('error')

# 数据入自己的库
#......

# 退出
driver.quit()