最近开发一个爬虫小工具,遇到一个问题,网站页面js请求服务端接口是加了自己生成的请求签名,一开始我尝试了各种算法来尝试生成这个签名,但没有成功,然后又分析前端js代码来尝试获取签名算法,但现在前端框架生成的js代码一坨一坨的还有混淆,实在是很难看懂,索性就放弃了。然后尝试浏览器插件Interceptor和postman interceptor确实是可以获取到js发起的请求的响应的全部内容,但毕竟是爬虫,用浏览器插件实在不方便,但interceptor给我提供了思路,然后搜索了一下,seleniumwire这个库确实可以实现interceptor。
直接上代码,关键部分都脱敏了,自己模仿修改适配自己要爬取的网站即可,平时用java比较多不怎么写python,python代码写的不好看不优雅望见谅。
seleniumwire使用了自己的ca.crt证书,浏览器默认是不信任的,可以自己导入到操作系统或浏览器来解决https的小红叉问题。参考:seleniumwrie导入ca.crt
pip3 install selenium-wire
pip3 install pymysql
from seleniumwire import webdriver
import time
import pymysql
#把爬取到的sign写入数据库
def update(data):
db = pymysql.connect(host="localhost",
user="root",
password="cheduzi",
database="spider",
init_command="SET SESSION time_zone='+08:00'"
)
db_curs = db.cursor()
update_sql = """update config set sign = '{sign}',update_time = now() where platform = 'xxx';""".replace("{sign}", data)
try:
print("sql:", update_sql)
db_curs.execute(update_sql)
db.commit()
print("update ok")
except:
db.rollback()
print("update error")
db.close()
# 请求拦截器
def interceptor_request(request):
print(
request.url,
request.response.headers
)
# 响应拦截器
def interceptor_response(request, response):
if request.url.startswith("https://xxx.com/api"):
# print(request.url, request.headers['sign'], request.body.decode('utf-8'))
# print(request.url, request.headers['sign'], response.body.decode('utf-8'))
sign = request.headers['sign']
print(request.url, sign)
if len(sign) != 0:
update(sign)
driver.quit()
if __name__ == '__main__':
#option参数来控制不打开浏览器界面,如果在调试阶段可去掉option参数
option = webdriver.ChromeOptions()
option.add_argument('headless')
option.add_argument('no-sandbox')
option.add_argument('disable-dev-shm-usage')
driver = webdriver.Chrome(chrome_options=option)
driver.response_interceptor = interceptor_response
driver.get('https://xxx.xxx.com/xxx/detail')
time.sleep(5)
driver.quit()