爬虫发送请求时,请求头中默认没有User-Agent,或提供非正常的UA
在请求时添加UA
requests模块发送请求时在headers参数中添加UA键值对
selenium默认自带被控制浏览器的UA,也可以替换UA
Referer是header的一部分,当浏览器向web服务器发送请求的时候,一般会带上Referer,告诉服务器我是从哪个页面链接过来的
爬虫发送请求时,请求头中默认情况下不会带上Referer字段
在请求时添加Referer
requests模块发送请求时在headers参数中添加Referer键值对,从抓包信息中复制Referer信息
selenium默认自带Referer
无论是否需要登陆,web服务器都可以在用户的浏览器中设置Cookie;Cookie是header的一部分,当浏览器向web服务器发送请求的时候,如果存在Cookie就一定会携带
web服务器检查请求头中的cookie是否是之前设置的cookie
携带cookie发送请求
requests模块发送请求时,使用requests.session自动处理cookie
用requests模块发送请求时,在cookies参数或在headers参数中,使用selenium获取的cookie;注意cookie的过期时间
构建cookie池(根据cookie的过期时间,定期批量获取的cookie,放到数据库中),requests模块发送请求时,使用从cookie池中获取的cookie
很多时候,网站利用用户的浏览器对返回的数据或请求的参数进行解密或加密,比如百度翻译PC版
利用用户的浏览器执行web服务器返回的js代码来对加密的响应内容进行解密(不常见)
利用用户的浏览器执行web服务器返回的js代码来对请求参数进行加密,之后再发送请求(常见)
python重写js代码的功能、或执行js代码拿到结果
完全看不懂js代码:selenium
完全看懂js代码:python重写js代码的功能
能够看懂js代码执行的大致过程:使用js2py模块运行相关的js代码,获取运行结果(js2py模块在下面将介绍到)
我们在浏览网站时,经常看见类似12306或者这样的等一些用户行为验证
对方服务器通过弹出验证码强制验证用户浏览行为
使用打码平台或深度学习的方式破解验证码
正常用户很难在很短的时间内打开需要点击才能访问的链接,那么网站就可以根据ip地址和cookie以及user-agent等能区分不同用户身份的信息来进行反爬
检测同一个ip在单位时间内是否发送了大量请求
经常和cookie以及user-agent配合检查
网上获取免费的代理ip
购买代理ip
使用代理ip池
构建代理ip池
requests模块发送请求使用proxies参数
selenium可以通过配置对象来使用代理ip
打开猫眼电影PC页面,右键检查用户评分,查看网页源代码
利用浏览器能够加载渲染并正确显示自定义字体的功能,使用自定义字体不影响正常用户浏览
从移动端页面获取数据
处理并解析自定义字体
打开去哪儿网PC端页面,搜索并查看飞机票信息
当我们仅了解js运行的大致情况,又不能使用selenium的时候,就可以使用js2py来解决js执行和js加密的问题
import js2py
js_str = '''
function func(x)
{
return x
}
'''
# 实例化js解释器对象
js_content = js2py.EvalJs()
js_content.execute(js_str) # 传入并执行js代码
# 调用js代码中的函数并获取返回值
ret = js_content.func('hahaha')
print(ret)
js_var = 'var abc = 1'
js_content.execute(js_var) # # 传入并执行js代码(变量)
# 获取js代码中的变量
print(js_content.abc)
# 向js执行解释器中传入变量
js_content.abc = 2
print(js_content.abc)
js_content = js2py.EvalJs()
js_content.execute(js代码)
ret = js_content.func('参数')
js_content.变量名
js_content.变量名 = 值
利用谷歌浏览器抓包确定登录的url、请求方法以及请求参数
通过谷歌浏览器抓包知道需要以下三步
获取rkey
url:http://activity.renren.com/livecell/rKey
请求方法:GET
密码加密js:
t.password = t.password.split("").reverse().join(""),
setMaxDigits(130);
var o = new RSAKeyPair(n.e,"",n.n),
r = encryptedString(o, t.password);
参考代码:
import requests
import json
import js2py
# 实例化session对象
session = requests.session()
# 自定义头文件
headers = {
"User-Agent": "Mozilla/5.0 (Linux; Android 5.0; SM-G900P Build/LRX21T) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/66.0.3359.139 Mobile Safari/537.36",
"X-Requested-With": "XMLHttpRequest",
"Content-Type":"application/x-www-form-urlencoded"
}
# 设置session的请求头信息
session.headers = headers
# 获取js代码中所需要的n值和rKey参数
response = session.get("http://activity.renren.com/livecell/rKey")
# print(response.content.decode())
n = json.loads(response.content)['data']
# 根据获取信息对密码进行加密
# 准备用户名和密码
phoneNum = "131..."
password = "****"
# 使用js2py生成js的执行环境:context
context = js2py.EvalJs()
# 拷贝使用到js文件的内容到本项目中
# 读取js文件的内容,使用context来执行它们
with open("BigInt.js", 'r', encoding='utf8') as f:
context.execute(f.read())
with open("RSA.js", 'r', encoding='utf8') as f:
context.execute(f.read())
with open("Barrett.js", 'r', encoding='utf8') as f:
context.execute(f.read())
# 向context环境中添加需要数据
context.t = {
'password': password}
context.n = n
# 执行加密密码的js字符
js = '''
t.password = t.password.split("").reverse().join(""),
setMaxDigits(130);
var o = new RSAKeyPair(n.e,"",n.n)
, r = encryptedString(o, t.password);
'''
context.execute(js)
# 通过context获取加密后密码信息
# print(context.r)
password = context.r
# 使用session发送登录请求
data = {
'phoneNum': '131....',
'password': password,
'c1':0,
'rKey':n['rkey']
}
response = session.post("http://activity.renren.com/livecell/ajax/clog", data=data)
print(response.content.decode())
# 访问需要登录的资源
response = session.get("http://activity.renren.com/home#profile")
print(response.content.decode())
总结:我们可以不断的去获取cooike然后把这些cookie储存起来,我们要用的时候随机拿一个,如果遇到过期的cooike就把它从储存的地方删除
总结:我们可以通过一些代理ip网站去获取一些代理ip,然后把这些ip储存起来,我们要用的时候随机拿一个,通过这个ip去访问我们需要爬取的网站,这样可以避免我们使用一个ip频繁访问而被封的情况。