案例URL:https://login3.scrape.center/
用户名:admin 密码:admin
首次访问网址,会跳转到登录界面,打开 开发者工具,点击Network,刷新页面,输入用户名和密码,点击登录,查看第二个login请求。此处的URL变更为:https://login3.scrape.center/api/login,Payload中返回username和password,Preview返回了token的值。
登录成功后跳转到URL对应的网页,点击 ?limit=18&offset=0 ,页面内容URL:https://login3.scrape.center/api/book/?limit=18&offset=0,根据Response Headers中的Content-Type分析,服务器返回的数据格式为json类型
点击Preview,展开results ,查看页面数据
基于JWT的网站通常采用前后端分离模式,数据的传输依赖于Ajax,登录验证依赖JWT的token认证。JWT经验证是有效的,服务器就返回相应的数据。
Request Headers中出现了一个Authorization字段,其键值也是token
步骤
1.模拟登录请求,保存返回的JWT
2.在之后的请求当中,在headers中加上Authorization字段,通过token验证,如何爬取内容
完整代码:
import requests
from urllib.parse import urljoin
import urllib3
BASEURL = 'https://login3.scrape.center/' # 首页
LOGIN_URL = urljoin(BASEURL, '/api/login') # 登录界面
INDEX_URL = urljoin(BASEURL, '/api/book') # 内容页面
USERNAME = 'admin' # 用户名
PASSWORD = 'admin' # 密码
urllib3.disable_warnings() # 忽视警告
# https://login3.scrape.center/api/login
json = {
"username": USERNAME,
"password": PASSWORD,
}
response_login = requests.post(LOGIN_URL, json=json, verify=False) # verify=False 取消证书验证
data = response_login.json()
print('Response json', data)
jwt = data.get('token')
print('JWT', jwt)
headers = {
"Authorization": f'jwt {jwt}'
} # jwt {jwt}中间有空格,漏打程序会报错。
# https://login3.scrape.center/api/book?limit=18&offset=0 第一页
# https://login3.scrape.center/api/book?limit=18&offset=18 第二页
# https://login3.scrape.center/api/book?limit=18&offset=36 第三页
params = {
"limit": 18,
"offset": 0
}
response_index = requests.get(INDEX_URL, params=params, headers=headers, verify=False)
print('Response_code', response_index.status_code) # 输出状态码
print('Response_URL', response_index.url) # 输出网页的URL
print(response_index.text) # 输出内容
上述代码中仅爬取第一页,如果需要爬取多页可以进行for循环
# 通过控制page的范围控制爬取的页数
# https://login3.scrape.center/api/book?limit=18&offset=0 第一页
# https://login3.scrape.center/api/book?limit=18&offset=18 第二页
# https://login3.scrape.center/api/book?limit=18&offset=36 第三页
for page in range(0, 10):
params = {
'limit': '18',
'offset': page * 18
}
response_index = requests.get(INDEX_URL, params=params, headers=headers, verify=False)
print('Response_code', response_index.status_code)
print('Response_URL', response_index.url)
print(response_index.text)