2020-10-25 Python爬虫 第一章urllib库与requests库,第四节,requests、urllib模拟登陆

第四节、requests|urllib模拟登陆

本节的主要说如何使用requests、urllib模拟登陆一些网站,主要说明如何去成功登陆一些网站。另外由于我们还没说到动态网页的爬取方式,故我们主要说一些简单的登陆(要么没有验证码,要么验证码是输出字母那种,而不是像拖动滑动验证码那种,这种拖动滑动验证码的是需要selenium的支持才能登陆)

1.1 使用cookies模拟登陆豆瓣

为啥要用cookies登陆,而不使用账号密码登录呢。读者仔细查看下面三张图片,就知道我们要使用cookies登陆

 

 下面我们来说说使用cookies来登录豆瓣网站,以下是我登陆后的豆瓣网站的部分类容。我们按F12打开开发者选项,找到NetWork下的doc,将下面的cookies复制下来

 这里小编附上了两种模拟登陆的方法一种是requests,一种是build_opener,两种方法都是独立运行过的,而且都能爬取,当然读者也能使用urlopen+request登陆。

需要注意的是若是读者多次重启程序都能成功,但后面再重启程序不能成功,这就说明是登陆太过于频繁了,出现了滑动验证码。这时读者只需将浏览器中的账号退出,重新登录一遍,破解掉滑动验证码后,程序又能运行了。但也不要太过于频繁,避免自己的IP被封了

爬取结果见下图

 

import requests
# 第一种方法
#构造请求头,注意这里几个必要的参数cookie,useragent,referer,host前两个不用我说了都懂,
# 对于豆瓣这种经常被爬取的网站,useragent一定需要改的
# referer 表示告诉服务器,你是从登陆成功后的首页('https://www.douban.com/')转到https://douban.com/people/224337678/下的
# host请求网站原始位置
# 一般这种大型的网站,最好把前一节说的重要参数都带上,但要注意accept_encoding这里小编就没带
headers = {
			'Cookie': 'bid=rPPt_3Vu3w4;... __utmb=30149280.4.10.1603608354',#将cookies值贴在上面,为了保护小编的账号信息,我这里就省略中间的,
			'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36',
			'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
			'Accept-Language': 'zh-CN,zh;q=0.9',
			'Connection': 'keep-alive',
			'Host': 'www.douban.com',
			'Referer': 'https://www.douban.com/'
			}
#将需要访问的页面传入
html = requests.get('https://douban.com/people/224337678/', headers = headers)
print(html.text)
#---------------------------------------------------------------------
#第二种方法
from urllib.request import build_opener,Request
#将刚才够早的headers传入Request下
r = Request('https://douban.com/people/224337678/',headers = headers)
opener = build_opener()
html = opener.open(r)
print(html.read().decode())

 下面就是我们成功爬取的后的部分网页源代码,可以看待“爬虫成功”这条信息在里面

 

2. 登陆知乎

读者可以分析向上面分析豆瓣一样分析知乎的登陆为网站,可以发现知乎的也是动态页面,我们依然使用上面的方法,使用cookies登录网站

我们下来看看我的知乎界面的内容

 这里小编用了三种方法,去登陆知乎,每种方法里的headers均有所差异,读者可以自行对比,三者输出结果均一致

见下面。需要说明的是由于知乎的网页源代码,不规范,故我们的输出内容也不咋协调

import requests
from urllib.request import Request,urlopen,build_opener
#构造请求头。注意requests下,此时accept-encoding在与不在都能返回正确的文本
headers = {'cookie': '_xsrf=po8AMhu3SASZQiO8V5n9wc3I7QCM45a4; ...KLBRSID=3d7feb8a094c905a519e532f6843365f|1603610646|1603610387',
			'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
			'referer': 'https://www.zhihu.com/',
            'accept-encoding': 'gzip, deflate, br',
			'accept-language': 'zh-CN,zh;q=0.9',
			'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'
           }
html = requests.get('http://zhihu.com/people/zhan-sui-xu-kong',headers = headers)
print(html.text)
print('-----------------------------------------------------------')
#后遭请求头,注意此时accept-encoding我将他删了,若不删除我们输出的内容是乱码,读者可以试试
headers = {'cookie': '_xsrf=po8AMhu3SASZQiO8V5n9wc3I7QCM45a4; ....KLBRSID=3d7feb8a094c905a519e532f6843365f|1603610646|1603610387',
			'accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9',
			'referer': 'https://www.zhihu.com/',
			'accept-language': 'zh-CN,zh;q=0.9',
			'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36'
           }
r = Request('http://zhihu.com/people/zhan-sui-xu-kong',headers = headers)
html = urlopen(r)
print(html.read().decode())
print("-----------------------------------------------------------")
#声明类
opener = build_opener()
headers = [('cookie','_xsrf=po8AMhu3SASZQiO8V5n9wc3I7QCM45a4; ....KLBRSID=3d7feb8a094c905a519e532f6843365f|1603610646|1603610387'),
			('accept','text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9'),
			('referer','https://www.zhihu.com/'),
			('accept-language','zh-CN,zh;q=0.9'),
			('user-agent','Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.79 Safari/537.36')
			 ]
#修改请求头,注意opener添加请求头是使用复制方式,而且headers为列表
opener.addheaders = headers
html = opener.open('http://zhihu.com/people/zhan-sui-xu-kong')
print(html.read().decode())

3.账号登录 

现在都2020年11月份了,现在很多网站对于登录窗口都做的比较好,对于反爬虫的手段越来越高级,所以我们在模拟登陆的时候能使用requests库去模拟登陆的网站越来越少,大多都是向上面那样要么是动态网页,或者是需要手机验证码(比如新浪),或者滑动验证之类的(美团),这几天小编一直在寻找可以用requests库去模拟登陆的,注册了30多个网站都没有找到合适的,甚至有的网站可以登录,但是验证码的图片地址是找不到的(我们学校的教务网站就是这样的),但读者也不必困扰,毕竟别人也不希望自家的网站被机器读取,但我们后面学到selenium的时候,这些东西就几乎不是问题。不过小编最终还是找到了一个比较适合模拟登陆练手的网站(找了快两天了,中间休息了半天,都快自闭了),现在我们开始模拟登陆这个网址http://pythonscraping.com/comment/reply/10

1、登陆一般是通过Post请求来实现的,其传递参数为一个表单,如果要成功登陆,我们需要查看该表单传递了哪些内容,然后构造表单做Post请求。怎么获取表单呢,第一步我们只需要打开浏览器按一下F12,找到network,再同时按住ctrl+R刷新一下,然后输入账号密码,第二步点击登陆查看其NetWork中的请求,第三步寻找name项目下,名字没有后缀的项(名字中带有login,user等字眼的)且在headers中拥有form_data信息(一般有你输入的部分或全部信息,如果满足上面信息,那就说明找对了)。注意每一步都不能少,且不能够打乱顺序。可以看看这个网站是如何寻找form_data的http://cnblogs.com/fanyuchen/p/7091041.html。知道是如何寻找formadata就可以了。

2.按上述方法找到form_data,具体步骤看 图上,可以看到我们有些信息没有输入比如form_id,但它为啥会出现在表单里呢,请看第三步

3. 我们重新打开刚才的网站,并右键检查我们需要输入信息附近的代码。我将content下的所有需要输入信息的标签全部就出来(包括input标签),可以看到我们需要输的信息如验证码、名字标签等都在里面。但是多了几个我们没有输入的标签如capatch_id,可以看到他的类型值为hidden,而且给网页指认了默认值370286(这网站每次刷新,captach_id值和上面图片值都会不一样,其它hidden对应的标签也一样),像这种字段我们称之为隐藏字段,它是反爬虫的一种手段。当我们提交表单时,若这些字段的默认值不在里面,或者被改变了,服务器会识别出这请求是机器人发出的,然后拒绝这个请求,毕竟浏览器用户是看不到这些值的。
细心的读者可以看到,上面图片对应的值还有op:submit,下面图片还有林外一个标签,对于这种标签它的类型是submit(相当于按钮),这也就说我们不需要输入。我们真正需要提交的是带有text、password、hidden等类型的。至于其他的网站具体问题具体分析。

4.

综上所述我们提交的表单里需要提交'name','subject','comment_body[und][0][value]','form_build_id','captcha_sid', 'captcha_token',form_id,captcha_response(验证码)这些字段,前面几个字段都还好说,最后一个就很麻烦,这里我就用了简单的方法将验证码图片下载下来,然后人工识别在输入。这里我们就不用了图片识别了,毕竟我们的内容是熟悉登陆步骤。下面附上模拟登陆的代码,若你的内容是首次输入而且登陆成功,则在返回TRUE,否则False这网站的验证码识别估计是网站作者自己搭建的,所以有时候会不准,注意区分大小写)。注意每次重启程序(不管登陆成功与否),都需要将“小白学习爬虫第一关模拟登陆a”这两段话改变一下。不然网站可能会记住你的错误登陆信息,你的登陆失败但依然会返回TRue

import requests
from bs4 import BeautifulSoup
#先发起一次请求,得到需要输入字段的信息
html = requests.get('http://pythonscraping.com/comment/reply/10')
#这里我提前用了一下解析器BeautifulSoup去帮我们获取网页信息,若读者不理解,可打开网页源代码,用正则表达式去获取相应的值
bs = BeautifulSoup(html.text,'html.parser')

#对于下面的步骤,我说的尽量详细一点
#找到input标签下,name属性为form_build_id的项目,
form_build_id_item  = bs.find('input',{'name':'form_build_id'})
form_build_id_dict=form_build_id_item.attrs
# 然后在用.attrs句获取这个标签的属性(以字典形式返回如{‘name’:‘form_build_id’,...}),在提取键为value的是
form_build_id = form_build_id_dict['value']

#同上获取form_id的对应值
form_id = bs.find('input',{'name':'form_id'}).attrs['value']
#同上获取captcha_sid的对应值
captcha_sid = bs.find('input',{'name':'captcha_sid'}).attrs['value']
#同上获取captcha_token的对应值
captcha_token = bs.find('input',{'name':'captcha_token'}).attrs['value']
#同上获取验证码的图片的地址,不过此时标签以及属性值改变了
img = bs.find('img',{'title':'Image CAPTCHA'}).attrs['src']

#下载验证码图片,并以二进制存储
img = 'http://pythonscraping.com' + img
with open('scraping.jpg','wb') as fp:
	html_img = requests.get(img)
	content = html_img.content
	fp.write(content)

print('form_build_id',form_build_id)
print('form_id',form_id)
print('captcha_sid',captcha_sid)
print('captcha_token',captcha_token)
print('imgurl',img)
#打开下载的图片,并读取验证码,然后输入(区分大小的写的)
captcha_response = input('请输入验证码:')
data = {'name': 'BlackWidowSpider',
			'subject': 'requests模拟登陆',
			'comment_body[und][0][value]': '小白学习爬虫第一关模拟登陆a',
			'form_build_id': form_build_id,
			'form_id': form_id,
			'captcha_sid': captcha_sid,
			'captcha_token': captcha_token,
			'captcha_response': captcha_response,
			}
#发起请求
html = requests.post('http://pythonscraping.com/comment/reply/10',data = data)
print(html.text)
#如果成功,则就返回TRue
print('小白学习爬虫第一关模拟登陆a' in html.text)
html.close()
#-----------------------------------------------------
'''以下是输出结果


form_build_id form-S4RuOhaAA5RCoxYnI5AoVB3kEOYlmrCHVdlMoDB_9_o
form_id comment_node_page_form
captcha_sid 370361
captcha_token c4202aac78c777a6bc76570099f8aff5
imgurl http://pythonscraping.com/image_captcha?sid=370361&ts=1603775326
请输入验证码:i6hfr
...
 <input type="text" id="edit-name" name="name" value="BlackWidowSpider" size="30" maxlength="60" class="form-text" />
...
 <input type="text" id="edit-subject" name="subject" value="requests模拟登陆" size="60" maxlength="64" class="form-text" />
...
 <div class="form-textarea-wrapper resizable"><textarea class="text-full form-textarea required" id="edit-comment-body-und-0-value" name="comment_body[und][0][value]" cols="60" rows="5">小白学习爬虫第一关模拟登陆a</textarea></div>
...

True
'''

也能使用Session()去模拟登陆,只需将最后请求处换为下面代码

import requests
session = requests.Session()
html = session .post('http://pythonscraping.com/comment/reply/10',data = data)
print(html.text)
#如果成功,则就返回TRue
print('小白学习爬虫第一关模拟登陆a' in html.text)
html.close()

4.使用urlopen时,只需将最后请求处换为下面代码

from urllib.request import Request,urlopen
from urllib.parse import urlencode
data = bytes(urlencode(data),'utf-8')
r = Request('http://pythonscraping.com/comment/reply/10',data = data)
html = urlopen(r)
html = html.read().decode()
print(html)
#如果成功,则就返回TRue
print('小白学习爬虫第一关模拟登陆a' in html)

 5.使用build_opener时,只需将最后请求处换为下面代码

from urllib.request import Request,urlopen,build_opener
from urllib.parse import urlencode
data = bytes(urlencode(data),'utf-8')
opener = build_opener()
html = opener.open('http://pythonscraping.com/comment/reply/10',data = data)
html = html.read().decode()
print(html)
#如果成功,则就返回TRue
print('小白学习爬虫第一关模拟登陆a' in html)

这一节的模拟登陆就到这里,主要是小编实在找不到合适的网站去模拟登陆(这几天收到骚扰电话频率都翻倍了),若以后遇到能登陆的网站,我在仔细说说

#下面一章我们将说如何去解析网页,就比如我们上面说到的BeautifulfSoup

#小编是一个理科生,文笔不好,大家能理解我的意思就行了。

#转载则请标明文章出处,谢谢。

#文中若有任何错误,欢迎大家积极指出,小编洗耳恭听。

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值