python爬虫基础Ⅴ

您所在的位置:网站首页 懂了么官网登录地址 python爬虫基础Ⅴ

python爬虫基础Ⅴ

#python爬虫基础Ⅴ| 来源: 网络整理| 查看: 265

文章目录 基础爬虫部分Ⅴ爬取饿了么上的附近餐馆cookiessessionPOST请求获取登录的cookie分析过程(1) 模拟发送验证码(2) 使用session模拟登录(3) 模拟输入地址,获取必要参数(4) 带cookies和参数请求餐馆列表(5) 代码整合

基础爬虫部分Ⅴ

这里打算用一个实例来简单说下cookie和会话。

也许看起来我下面写的做这个任务很顺利,其实都是经过摸索得出来的,像一些参数在哪里获得,哪些参数是代表什么意思,都是要经过不断尝试、对比才得出答案,所以要有耐心哦!

爬取饿了么上的附近餐馆

要求就是要爬取附近餐馆的店名和评分(其实可以获取到更多)。

运行过程大概这样:输入手机号码 -> 输入验证码 -> 输入所在地址 -> 选择具体地址 -> 获取数据

在这里插入图片描述 在这里插入图片描述

cookies

其实,你对cookies并不陌生,我敢肯定你见过它。比如一般当你登录一个网站,你都会在登录页面看到一个可勾选的选项“记住我”,如果你勾选了,以后你再打开这个网站就会自动登录,这就是cookie在起作用。

当然,cookies也是有时效性的,过期后就会失效。你应该有过这样的体验:哪怕勾选了“记住我”,但一段时间过去了,网站还是会提示你要重新登录,就是之前的cookies已经失效。

session

所谓的会话,你可以理解成我们用浏览器上网,到关闭浏览器的这一过程。session是会话过程中,服务器用来记录特定用户会话的信息。比如你打开浏览器逛购物网页的整个过程中,浏览了哪些商品,在购物车里放了多少件物品,这些记录都会被服务器保存在session中。

如果没有session,你加购了很多商品在购物车,打算结算时,发现购物车空无一物Σ(っ°Д°;)っ,因为服务器根本没有帮你记录你想买的商品。

session和cookies的关系还非常密切——cookies中存储着session的编码信息,session中又存储了cookies的信息。当浏览器第一次访问购物网页时,服务器会返回set-cookies的字段给浏览器,而浏览器会把cookies保存到本地。

等浏览器第二次访问这个购物网页时,就会带着cookies去请求,而因为cookies里带有会话的编码信息,服务器立马就能辨认出这个用户,同时返回和这个用户相关的特定编码的session。

这也是为什么你每次重新登录购物网站后,你之前在购物车放入的商品并不会消失的原因。因为你在登录时,服务器可以通过浏览器携带的cookies,找到保存了你购物车信息的session。

我们通常通过创建一个session来处理cookies,它会帮我们自动保持cookies。

POST请求

之前学的get可以带着参数请求,且get请求的参数会在url上显示出来。其实post也可以带参请求,只是参数不会显示在url上,而是隐藏起来。 像账号密码这种私密的信息,就应该用post的请求。如果用get请求的话,账号密码全部会显示在网址上,这显然不科学!你可以这么理解,get是明文显示,post是非明文显示。 通常,get请求会应用于获取网页数据,比如我们之前学的requests.get()。post请求则应用于向网页提交数据,比如提交表单类型数据(像账号密码就是网页表单的数据)。 get 和 post是两种最常用的请求方式,除此之外,还有其他类型的请求方式,如head、options等,但一般很少用到。

获取登录的cookie

你在能登录的网站上,打开第一个请求的【headers】面板里,【requests headers】存储的是浏览器的请求信息,【response headers】存储的是服务器的响应信息。我们要找的cookies就在其中。 你会看到在【response headers】里有set-cookies的参数,就是服务器往浏览器写入了cookies。

http://httpbin.org/post 这个链接可以用来测试POST请求,它可以输出请求的一些信息,其中包含我们传递的data参数(get请求中用的参数是params,post请求用的是data)。现在做个示范。

import requests url = 'http://httpbin.org/post' #这个链接可以用来测试POST请求,它可以输出请求的一些信息,其中包含我们传递的data参数 headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36' } #请求头 data = { 'user' : "username", 'password' : '123456' } #传递的参数 res = requests.post(url,data=data,headers=headers) print(res.status_code) #打印出请求的状态码,若状态码等于200,则证明请求成功。 print(res.text) #输出请求的信息,我们传递的参数出现在form字段中,表明是模拟了表单提交的方式,即POST方式传输数据。 cookies = res.cookies #提取cookies的方法:调用requests对象(login_in)的cookies属性获得登录的cookies,并赋值给变量cookies。

但是我前面说了,由于会话可以自动保持cookies,所以通常创建一个会话来处理cookie,后面再要用到时就不用传入cookies。

import requests session = requests.Session() #用requests.session()创建session对象,赋值给session,相当于创建了一个特定的会话,帮我们【自动保持了cookies】。后面要用的时候就不用传入cookies url = 'http://httpbin.org/post' #这个链接可以用来测试POST请求,它可以输出请求的一些信息,其中包含我们传递的data参数 headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36' } data = { 'user' : "username", 'password' : '123456' #其实传什么参数都可以,毕竟这只是个测试POST请求的网站 } res = session.post(url,data=data,headers=headers) print(res.status_code) #打印出请求的状态码,若状态码等于200,则证明请求成功。 #无需再提取cookies了,因为session帮我们自动保持了cookie(我不是复读机)。 分析过程

下面开始分析吧!

借助cookies的相关知识,使用Python登录饿了么网站,爬取自己家附近的餐厅列表。

网站地址:https://www.ele.me/home/

因为饿了么要登录才能获取餐馆列表,所以我们需要用使用cookies模拟登陆.

(1) 模拟发送验证码

体验登录地址:https://h5.ele.me/login/

是一个需要手机和验证码登录的界面。我们需要先模拟发送验证码的请求,再模拟登录的请求。

在页面按下 F12 -> Network -> XHR -> 网页刷新 -> 输入手机号码后点击【获取验证码】(如果发送验证码不成功,说明你发太多次了,建议换个手机号码或等几个小时)

此时会加载出一个新的请求为mobile_send_code,很明显就是“发送手机验证码”的意思,点开它,

在这里插入图片描述

然后拉到下面【Request Payload】,这里是模拟发送验证码请求所需要的一些参数,mobile参数的值是你的手机号码。

在这里插入图片描述

注意:请求验证码时,会返回一个json,json里会有validate_token的值(Preview里可以看到),先把它记下,在我们输入账号验证码模拟登录的时候会用到它。

然后我们可以写发送验证码的代码啦。

import requests session = requests.session() #用requests.session()创建session对象 headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36' } #模拟发送验证码 tel = input("请输入手机号码:") url1 = 'https://h5.ele.me/restapi/eus/login/mobile_send_code' data1 = { 'captcha_hash': '', 'captcha_value': '', 'mobile': tel, 'scf': ''} #注意:请求验证码时,会返回一个json,json里会有【validate_token】的值,它在登录时作为参数用到,这里我们把它记住,赋值给token token = session.post(url1, headers=headers, data=data1).json()['validate_token'] (2) 使用session模拟登录

然后我们勾选一下Preserve log保存日志,再输入验证码,点击【登录】,这时会加载出一个login_by_mobile的请求,明显是手机号码登录的意思,点开它:

在这里插入图片描述 参数里面的倒数第二个是刚才收到的手机验证码,最后一个就是我们刚才模拟发送验证码请求时响应返回的值token,这里就用到了。于是可以接着往下写模拟登录的代码:

#*******接着上一个代码后面******* #模拟登陆[login_by_mobile] code = input('请输入验证码:') url2 = 'https://h5.ele.me/restapi/eus/login/login_by_mobile' data2 = { 'mobile': tel, 'scf': 'ms', 'validate_code': code, 'validate_token': token } session.post(url2, headers=headers, data=data2) #模拟用手机号码登陆

这下我们已经登录好了,就可以去获取餐馆列表啦✿✿ヽ(°▽°)ノ✿

(3) 模拟输入地址,获取必要参数

为了请求餐馆列表,我们需要几个所在地址的关键参数(至于为什么,往后看就知道辽):

geohash:通过搜索得之,这是一个能够代表地理位置的字符串。latitude:纬度longitude:经度

这三个参数,都需要模拟输入地址来获得。 体验输入地址:https://www.ele.me/home/

提示:1.本步骤不需要模拟登录。2.在模拟该请求时需要用到城市的geohash值,可在 XHR 里查看自己城市的geohash值。

例如下面是我获得【五一广场】的地理位置信息,看看这个请求的参数,这些是长沙的地理位置信息:

在这里插入图片描述

再看一下【Preview】里面,有加载出来的详细地址,地名是键为name的值,具体地址是键为short_address的值,然后地址的地理位置信息(前边那个图里的是城市的地理位置)也在里面,要把这个列表打印出来供用户选择。那么首先我们先要模拟请求地址,继续完善代码:

#*******又接着上一段代码******* place = input('请输入你的收货地址:') address_url = 'https://www.ele.me/restapi/bgs/poi/search_poi_nearby?' # 在模拟该请求时需要用到城市的geohash值,可在XHR里查看自己城市的geohash值(例如深圳:ws105rz9smwm) params = {'geohash':'wt029fxwdpkh', 'keyword':place, 'latitude':'28.227779', 'limit':'20', 'longitude':'112.938858', 'type':'nearby'} # 将要传递的参数封装成字典,键与值都要用字符串,其中keyword对于的值是place。 address_res = requests.get(address_url, params=params) # 发起请求,将响应的结果,赋值给address_res address_json = address_res.json() # 将响应的结果转为列表/字典,此处是列表 print('以下,是与'+place+'相关的位置信息:\n') n = 0 for address in address_json: #每个address是一个字典 print(str(n)+'. '+address['name']+':'+address['short_address']+'\n') n = n+1 address_num = int(input('请输入您选择位置的序号:')) # 让用户选择序号。

由于在 restaurants 请求需要用到 地址的一些参数值,然后根据用户选择,获取收获地址的参数:

final_address = address_json[address_num] geohash = final_address['geohash'] latitude = final_address['latitude'] longitude = final_address['longitude'] (4) 带cookies和参数请求餐馆列表

然后我再点选【五一广场】,下一个页面就有餐馆列表了,在restaurants请求里:

在这里插入图片描述

然后去【Preview】里选出我们要的数据就可以啦,继续完善代码:

url3 = 'https://www.ele.me/restapi/shopping/restaurants?'# 使用带有餐馆列表的那个XHR地址。 params = { 'extras[]': 'activities', 'geohash': geohash, 'latitude': latitude, 'limit': '24', 'longitude': longitude, 'offset': '0', 'terminal': 'web' } # 将参数封装,其中geohash和经纬度,来自前面获取到的数据。 restaurants_res = session.get(url3, params=params)# 带参数发起请求(GET请求参数用params表示,POST请求参数用data表示) restaurants_json = restaurants_res.json()# 把response对象,转为json。 #print(restaurants_json) print( '\n\n' +'在' + address_json[address_num]['name'] + '附近的餐馆有:') #这是用户在上一步选择的地址 for restaurant in restaurants_json: # restsurants最外层是一个列表,它可被遍历。restaurant则是字典,里面包含了单个餐厅的所有信息。 print('店名:'+restaurant['name'],'评分:'+str(restaurant['rating'])) print() (5) 代码整合

其实要一路顺利做下来真的不简单,多尝试几次吧!ヾ(◍°∇°◍)ノ゙理清楚各步骤间的关系,下面是我的完整代码:

#!/usr/bin/env python # -*- coding:utf-8 -*- import requests session = requests.session() #创建会话 headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36' } #模拟发送验证码 tel = input("请输入手机号码:") url1 = 'https://h5.ele.me/restapi/eus/login/mobile_send_code' data1 = { 'captcha_hash': '', 'captcha_value': '', 'mobile': tel, 'scf': ''} #注意:请求验证码时,会返回一个json,json里会有【validate_token】的值,它在登录时作为参数用到 token = session.post(url1, headers=headers, data=data1).json()['validate_token'] #模拟登陆[login_by_mobile] code = input('请输入验证码:') url2 = 'https://h5.ele.me/restapi/eus/login/login_by_mobile' data2 = { 'mobile': tel, 'scf': 'ms', 'validate_code': code, 'validate_token': token } session.post(url2, headers=headers, data=data2) #登陆 #由于在 restaurants 请求需要用到 地址的一些参数值,先获取地址的参数 place = input('请输入你的收货地址:') address_url = 'https://www.ele.me/restapi/bgs/poi/search_poi_nearby?' # 因为我们的geohash使用了深圳的值,所以推荐你测试的时候使用“腾讯大厦”。 # 在模拟该请求时需要用到城市的geohash值,可在XHR里查看自己城市的geohash值(例如深圳:ws105rz9smwm,下边的是长沙的) params = {'geohash':'wt029fxwdpkh', 'keyword':place, 'latitude':'28.227779', 'limit':'20', 'longitude':'112.938858', 'type':'nearby'} # 将要传递的参数封装成字典,键与值都要用字符串,其中keyword对于的值是place。 address_res = requests.get(address_url, params=params) # 发起请求,将响应的结果,赋值给address_res address_json = address_res.json() # 将响应的结果转为列表/字典,此处是列表 print('以下,是与'+place+'相关的位置信息:\n') n = 0 for address in address_json: #每个address是一个字典 print(str(n)+'. '+address['name']+':'+address['short_address']+'\n') n = n+1 address_num = int(input('请输入您选择位置的序号:')) # 让用户选择地址的序号,再记下地址的相关参数 final_address = address_json[address_num] geohash = final_address['geohash'] latitude = final_address['latitude'] longitude = final_address['longitude'] #带cookies请求餐馆列表 url3 = 'https://www.ele.me/restapi/shopping/restaurants?'# 使用带有餐馆列表的那个XHR地址。 params = { 'extras[]': 'activities', 'geohash': geohash, 'latitude': latitude, 'limit': '24', 'longitude': longitude, 'offset': '0', 'terminal': 'web' } # 将参数封装,其中geohash和经纬度,来自前面获取到的数据。 restaurants_res = session.get(url3, params=params)# 发起请求,将响应的结果,赋值给restaurants_res restaurants_json = restaurants_res.json()# 把response对象,转为json。 #print(restaurants_json) print( '\n\n' +'在' + final_address['name'] + '附近的餐馆有:' + '\n') #这是用户在上一步选择的地址 for restaurant in restaurants_json: # restsurants最外层是一个列表,它可被遍历。restaurant则是字典,里面包含了单个餐厅的所有信息。 print('店名:'+restaurant['name'],'评分:'+str(restaurant['rating'])) print()

————————每个人都在抱怨生活不易,可是都在默默为生活打拼————————



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3