文章目录
1.使用requests模块访问登录后才能访问的资源
我们是服务端工程师
我们在写web服务器程序的使用如何判断一个客户端是否登录了
当用户登录服务器后,我就写一个Cookie到浏览器,这个cookie记录我们服务器端session id
用户再发送请求就会携带这个cookie,根据中sessionid找到服务端该拥有对应的session; session中就记录用户相关信息.
cookie与session区别
相同点:
都是用于记录客户端相关信息的.
区别:
- cookie:
存储位置: 浏览器(客户端)
安全性: 不安全, 其他人可以分析cookie, 模仿用户发送请求.
大小限制: cookie最大不能超过4K,很多浏览器要求一个服务器最多只能存20个cookie
- session:
存储位置: 服务器
安全性: 安全, 其他人无法获取
大小限制:没有大小显示, 如果用户量巨大,那么session会降低服务器性能.
我们是爬虫工程师:
如何获取服务端登录后的资源(三种方式)
1.在请求头上指定cookie信息
注意: 演示获取请求URL和响应的URL, 因为这两个可能不一样.
2.发送请求的时候单独指定cookie信息
携带登录后的cookie发送请求; cookie登录后就不变了,存活时间很长.
3.使用requests模块中的session对象,
会记录登录后的cookie信息,来保持会话
步骤:
实例化session对象(session对象发送请求与requests是一样的)
session = requests.session()
使用session对象,进行登录,登录后seesion对象会记录用户相关的cookie信息
session.post(url,data=data)
再使用记录cookie信息对象session访问个人主页
session.get(url)
案例: 登录人人网个人主页
http://www.renren.com/965194180/profile
代码: 携带cookie访问登录后的资源
import requests
cookie_str = "anonymid=jfp6v2r3wcyq2c; first_login_flag=1; ln_uact=15565280933; ln_hurl=http://head.xiaonei.com/photos/0/0/men_main.gif; depovince=GW; _r01_=1; JSESSIONID=abcpmDwUaOcxn8lYqFFkw; ick_login=246b444c-2324-4bc5-a963-e519767a5273; jebe_key=2a802dfe-3087-4ee8-a4d0-5ac91ef689a8%7Cd1c66006be65eb42497ec9dcb5438885%7C1523098186912%7C1%7C1523098187581; wp_fold=0; jebecookies=33e8b4a6-cd76-40dc-b037-8779bf53888f|||||; _de=A64335C255985C873F16E7D5D4146F99; p=601440860cf468bf584d5a11c9aa14170; t=20e76eb86251529f24a4e18efaec58f10; societyguester=20e76eb86251529f24a4e18efaec58f10; id=965194180; xnsid=5ba237e6; loginfrom=syshomef"
url = "http://www.renren.com/965194180/profile"
# 方式1: 在请求头中指定cookie信息
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
# "Cookie": cookie_str
}
# 方式2: 使用字典记录每一个cookie, 键:=前面的 值:=后的
# one_cookie = anonymid=jfp6v2r3wcyq2c
cookie_dic = {one_cookie.split("=")[0]
:one_cookie.split("=")[1] for one_cookie in cookie_str.split("; ")}
# print(cookie_dic)
response = requests.get(url, headers= headers, cookies=cookie_dic)
if response.status_code == 200:
# print(response.content.decode())
with open("我的个人主页.html", "wb") as f:
f.write(response.content)
方式3:使用session登录,然后访问登录后的资源
import requests
# * 使用requests模块中的session对象,记录登录后的cookie信息
# 步骤:
# 1. 获取session对象
session = requests.session()
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_13_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36",
}
# 2. 使用session对象,进行登录,登录后seesion对象会记录用户相关的cookie信息
# 发送URL是什么? 需要传入的数据是什么?
login_url = "http://www.renren.com/PLogin.do"
data = {
"email":"15565280933",
"password":"a123456"
}
response = session.post(login_url, data=data, headers=headers)
print(response.status_code)
print(response.content.decode())
# 3. 再使用记录cookie信息对象session访问个人主页
profile_url = "http://www.renren.com/965194180/profile"
response = session.get(profile_url)
with open("李德山_个人主页.html", "wb") as f:
f.write(response.content)
小结: 如何访问登录后的资源
发送请求的时候, 在headers中指定Cookie字符串
发送请求的时候, 通过cookies参数指定, 是一个字典
使用session进行登录, 登录后使用session访问登录后资源,这个时候session会自动携带cookie信息.
带上cookie利弊与抉择
-
带上cookie、session的好处:
很多网站必须登录之后(或者获取某种权限之后)才能能够请求到相关数据
-
带上cookie、session的弊端:
一套cookie和session往往和一个用户对应.请求太快,请求次数太多,容易被服务器识别为爬虫。从而是账号收到损害
cookie使用建议
1.不需要cookie的时候尽量不去使用cookie
2.为了获取登录之后的页面,我们必须发送带有cookies的请求,此时为了确保账号安全应该尽量降低数据采集速度
2.如何找POST请求的URL和要发送的数据
我们要模拟用户登录,必须发送POST, 发送POST请求就必须有URL和要传输的数据.
方式1: 通过表单找出POS的URL
1.使用chrome的选择工具,选择表单的输入框,看Elements中的定位的位置,向上找form标签中action中URL
2.找POST请求中提交数据 使用chrome的选择工具,选择表单的输入框, 查看name属性 以人人网为例:
方式2 抓包,寻找POST的url地址
右键 -> 检查 -> network -> 刷新
- 注意: 勾选perserve log按钮,防止页面跳转找不到url
- 点击要查看的URL -> 选择headers选项卡
- 最上面是请求的URL
- 最下面是请求的数据
寻找post数据,确定参数
我们录入的
固定不变的数据
上一次或上几次请求获取到的数据
通过js生成
小结:- 通过表单找出POS的URL和需要传递的数据
- 通过抓包,寻找POST的URL地址
- 通过抓包,寻找POST的URL地址
- 通过表单找出POS的URL和需要传递的数据
js逆向-定位和调试js
1.监听鼠标点击事件
通过点击按钮,然后点击Event Listener,部分网站可以找到绑定的事件,对应的,只需要点击即可跳转到js的位置
1.通过search all
总结:找生成生成数据的js代码,两种方法
- 监听鼠标点击事件
- 通过search all
- 调试js
调试js
3.requests模块发送请求的小技巧
reqeusts.util.dict_from_cookiejar 把cookie对象转化为字典
import requests
# 1、reqeusts.util.dict_from_cookiejar 把cookie对象转化为字典
url = 'http://www.baidu.com'
response = requests.get(url)
print(response.cookies)
cookjar = response.cookies
# 将cookjar对象转换成字典类型数据
dict_cookies = requests.utils.dict_from_cookiejar(cookjar)
print(dict_cookies)
# 将字典类型数据转换成cookjar对象
print(requests.utils.cookiejar_from_dict(dict_cookies))
如何进行URL的编码与解码
- requests.util.unquote() URL解码
- requests.util.quote() URL编码
response = requests.get("http://www.baidu.com?kw='黑马程序员'")
print(response.url) # http://www.baidu.com/?kw='%E9%BB%91%E9%A9%AC%E7%A8%8B%E5%BA%8F%E5%91%98'
# 我们直接打印响应的URL都是经过URL编码后的字符串, 如果我们想看到原始URL该怎么办呢?
# 我们可以使用URL解码, 把字符串进行还原
url = requests.utils.unquote(response.url) # http://www.baidu.com/?kw='黑马程序员'
print(url) # http://www.baidu.com/?kw='黑马程序员'
# 如果需要对URL进行编码可以使用quote
encode_url = requests.utils.quote(url)
print(encode_url) # http%3A//www.baidu.com/%3Fkw%3D%27%E9%BB%91%E9%A9%AC%E7%A8%8B%E5%BA%8F%E5%91%98%27
请求 SSL证书验证
response = requests.get("https://www.12306.cn/mormhweb/ ", verify=False)
response = requests.get("https://www.12306.cn/mormhweb", verify=False)
print(response.status_code)
print(response.content.decode())
设置超时
response = requests.get(url,timeout=3)
url = 'http://www.youtube.com'
response = requests.get(url, timeout=3)
4.retrying模块的使用
使用超时参数能够加快我们整体的请求速度,但是在正常的网页浏览过成功,如果发生速度很慢的情况,我们会做的选择是刷新页面,那么在代码中,我们是否也可以刷新请求呢?
对应的,retrying模块就可以帮助我们解决
retrying模块的使用
retrying模块的地址:https://pypi.org/project/retrying/
retrying 模块的使用
- 使用retrying模块提供的retry模块
- 通过装饰器的方式使用,让被装饰的函数反复执行
- retry中可以传入参数
stop_max_attempt_number
,让函数报错后继续重新执行,达到最大执行次数的上限,如果每次都报错,整个函数报错,如果中间有一个成功,程序继续往后执行
retrying和requests的简单封装
实现一个发送请求的函数,每次爬虫中直接调用该函数
实现一个发送请求的函数,每次爬虫中直接调用该函数即可实现发送请求,在其中
- 使用timeout实现超时报错
- 使用retrying模块实现重试
代码参考:
# parse.py
import requests
from retrying import retry
headers = {}
#最大重试3次,3次全部报错,才会报错
@retry(stop_max_attempt_number=3)
def _parse_url(url)
#超时的时候回报错并重试
response = requests.get(url, headers=headers, timeout=3)
#状态码不是200,也会报错并重试
assert response.status_code == 200
return response
def parse_url(url)
try: #进行异常捕获
response = _parse_url(url)
except Exception as e:
print(e)
#报错返回None
response = None
return response
5.chrome浏览器部分使用方法介绍
掌握chrome在爬虫中的使用
- 新建隐身窗口
为什么需要新建隐身窗口
在打开隐身窗口的时候,第一次请求某个网站是没有携带cookie的,和代码请求一个网站一样,不携带cookie。这样就能够尽可能的理解代码请求某个网站的结果;除非数据是通过js加载出来的,不然爬虫请求到的数据和浏览器请求的数据大部分时候都是相同的
chrome中network的更多功能
Perserve log
默认情况下,页面发生跳转之后,之前的请求url地址等信息都会消失,勾选perserve log后之前的请求都会被保留
filter过滤
在url地址很多的时候,可以在filter中输入部分url地址,对所有的url地址起到一定的过滤效果,具体位置在上面第二幅图中的2的位置
观察特定种类的请求
在上面第二幅图中的3的位置,有很多选项,默认是选择的all,即会观察到所有种类的请求
很多时候处于自己的目的可以选择all右边的其他选项,比如常见的选项:
XHR:大部分情况表示ajax请求
JS:js请求
CSS:css请求
但是很多时候我们并不能保证我们需要的请求是什么类型,特别是我们不清楚一个请求是否为ajax请求的时候,直接选择all,从前往后观察即可,其中js,css,图片等不去观察即可
不要被浏览器中的一堆请求吓到了,这些请求中除了js,css,图片的请求外,其他的请求并没有多少个