+ 方式原理
爬虫爬取数据时,有些数据并不能让游客访问到,这时候就需要进行登录,再爬取数据,登录后再爬取的手段很多,但核心都是通过cookie的方式来记录身份信息,因此模拟登录的核心在于对cookie的使用。
参考链接:https://www.cnblogs.com/chenxiaohan/p/7654667.html
(1)直接使用已知cookie访问
简单地说cookie保存在发起请求的客户端中,服务器利用cookie来区分不同的客户端。因为http是一种无状态的连接,当服务器一下子收到好几个请求时,是无法判断出哪些请求是同一个客户端发起的。而“访问登录后才能看到的页面”这一行为,恰恰需要客户端向服务器证明:“我是刚才登录过的那个客户端”。于是就需要cookie来标识客户端的身份,以存储它的信息(如登录状态)。
当然,这也意味着,只要得到了别的客户端的cookie,我们就可以假冒成它来和服务器对话。这给我们的程序带来了可乘之机。
我们先用浏览器登录,然后使用开发者工具查看cookie。接着在程序中携带该cookie向网站发送请求,就能让你的程序假扮成刚才登录的那个浏览器,得到只有登录后才能看到的页面。
手动复制浏览器的cookie到程序中访问。
(2)模拟登录后再携带得到的cookie访问
我们先在程序中向网站发出登录请求,也就是提交包含登录信息的表单(用户名、密码等)。从响应中得到cookie,今后在访问其他页面时也带上这个cookie,就能得到只有登录后才能看到的页面。
(3)模拟登录后用session保持登录状态
session是会话的意思。和cookie的相似之处在于,它也可以让服务器“认得”客户端。简单理解就是,把每一个客户端和服务器的互动当作一个“会话”。既然在同一个“会话”里,服务器自然就能知道这个客户端是否登录过。
(4)使用无头浏览器访问
功能强大,几乎可以对付任何网页,但会导致代码效率低。
如果能在程序里调用一个浏览器来访问网站,那么像登录这样的操作就轻而易举了。在Python中可以使用Selenium库来调用浏览器,写在代码里的操作(打开网页、点击……)会变成浏览器忠实地执行。这个被控制的浏览器可以是Firefox,Chrome等,但最常用的还是PhantomJS这个无头(没有界面)浏览器。也就是说,只要把填写用户名密码、点击“登录”按钮、打开另一个网页等操作写到程序中,PhamtomJS就能确确实实地让你登录上去,并把响应返回给你。
具体使用程序来登录的话,方法有2种:简单的网页登录使用后者即可,复杂的使用前者。 https://www.jianshu.com/p/db5878e711d3
1.通过selenium进行浏览器模拟登录(简单粗暴)
2.通过分析登录页面,获取登录接口和提交表单进行登录验证
+ post方式登录网站,需要先将必要信息填充到一个dict中,我怎么知道需要哪些信息填写到dict中呢?我怎么知道需要post的地址url是哪个呢?
要post的url就是有输入用户名和密码框的那个页面的地址;登录豆瓣,用fidder工具查看Method是post的那个包,
打开fidder抓包工具后,浏览器显示“您的连接不是私密连接”原因及解决方案:Fiddler 是一个使用本地 127.0.0.1:8888 的 HTTP 代理,任何能够设置 HTTP 代理为 127.0.0.1:8888 的浏览器和应用程序都可以使用 Fiddler。Fiddler是位于客户端和服务器端的HTTP代理,客户端的所有请求都要先经过Fiddler,然后转发到相应的服务器,反之,服务器端的所有响应,也都会先经过Fiddler然后发送到客户端,基于这个原因,Fiddler支持所有可以设置http代理为127.0.0.1:8888的浏览器和应用程序。
解决方案是Fiddler添加https根证书,Tools - Fiddlers Options-HTTPS-Actions导出根证书放在桌面上,双击证书安装即可,安装之后IE浏览器可以正常访问网页。
+ requests模拟登录京东
import requests
from bs4 import BeautifulSoup
import time
class JDlogin(object):
def __init__(self,un,pw):
self.headers = {'User-Agent':"Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)",
'Accept':'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Encoding':'gzip, deflate, sdch',
'Accept-Language':'zh-CN,zh;q=0.8',
'Connection':'keep-alive',
}
self.session = requests.session()
self.login_url = "http://passport.jd.com/uc/login"
self.post_url = "http://passport.jd.com/uc/loginService"
self.auth_url = "https://passport.jd.com/uc/showAuthCode"
self.un = un
self.pw = pw
def get_authcode(self,url):
self.headers['Host'] = 'authcode.jd.com'
self.headers['Referer'] = 'https://passport.jd.com/uc/login'
response = self.session.get(url, headers = self.headers)
with open('authcode.jpg','wb') as f:
f.write(response.content)
authcode = input("plz enter authcode:")
return authcode
def get_info(self):
'''获取登录相关参数'''
try:
page = self.session.get(self.login_url, headers = self.headers )
soup = BeautifulSoup(page.text)
input_list = soup.select('.form input')
data = {}
data['uuid'] = input_list[0]['value']
data['eid'] = input_list[4]['value']
data['fp'] = input_list[5]['value']
data['_t'] = input_list[6]['value']
rstr = input_list[7]['name']
data[rstr] = input_list[7]['value']
acRequired = self.session.post(self.auth_url, data={'loginName':self.un}).text #返回({"verifycode":true})或({"verifycode":false})
if 'true' in acRequired:
print ('need authcode, plz find it and fill in ')
acUrl = soup.select('.form img')[0]['src2']
acUrl = 'http:{}&yys={}'.format(acUrl,str(int(time.time()*1000)))
authcode = self.get_authcode(acUrl)
data['authcode'] = authcode
else:
data['authcode'] = ''
except Exception as e:
print (e)
finally:
return data
def login(self):
postdata = self.get_info()
postdata['loginname'] = self.un
postdata['nloginpwd'] = self.pw
postdata['loginpwd'] = self.pw
try:
self.headers['Host'] = 'passport.jd.com'
self.headers['Origin'] = 'https://passport.jd.com'
self.headers['X-Requested-With'] = 'XMLHttpRequest'
login_page = self.session.post(self.post_url, data = postdata, headers = self.headers)
print (login_page.text) #若返回{“success”:”http://www.jd.com”},说明登录成功
except Exception as e:
print (e)
if __name__=="__main__":
username = input("plz enter username:")
password = input("plz enter password:")
JD = JDlogin(username,password)
JD.login()
+ Cookie问题
使用requests模拟登陆网站时需要手工构造复杂的模拟请求头,需要抓包分析post数据,可以通过selenium进行模拟登陆,然后将Cookies传入requests,最终用requests进行网站的抓取。优点就是不但规避了“selenium”其本身抓取速度慢的问题(因为仅仅用其作为登陆),又规避了利用requests登陆时需要制作繁琐的Cookies的过程(因为是从selenium直接拿来cookies)。