python reptile basis Ⅴ-- request with cookies, session: What hungry - nearby restaurant information



Reptiles base portion Ⅴ

Here we intend to use an example to simply under the cookie and session.

I wrote the following may look to do this task very well, in fact, are groping after get out of, like where to get some parameters, which parameters representative of what that means, are to go through to keep trying, comparing to arrive at the answer, so Be patient Oh!

Crawling hungry nearby restaurants on it

Requirement is to crawl near the restaurant its name and scoring (in fact, you can get to more).

Probably run this process: enter the phone number -> Enter the code -> Enter the address where -> select specific address -> Get Data

Here Insert Picture Description
Here Insert Picture Description


cookies

In fact, you are cookiesno stranger, I'm sure you've seen it. For example, generally when you log in to a website, you will see a login page you can check the option "Remember me", if you checked, and then after you open this site will automatically log, which is cookieat work.

Of course, cookiesis time-sensitive, will expire after the failure. You should have had this experience: even check the "remember me", but some time later, the website will still prompt you to log in again, that before cookieshad expired.


session

The so-called session, you can be understood as we use the Internet browser, close to the process browser. sessionIs the session, the server used to record information for a particular user session. For example, you open the browser visiting the whole process of shopping pages, browse the merchandise which, in the shopping cart, the number of items, these records will be stored on the server sessionin.

If not session, you add a lot of merchandise purchased in the shopping cart, when going to the settlement, discovered cart empty Σ (っ° Д °;)っbecause the server did not help you record you want to buy goods.

sessioncookies的关系还非常密切——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,很明显就是“发送手机验证码”的意思,点开它,

Here Insert Picture Description

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

Here Insert Picture Description

注意:请求验证码时,会返回一个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的请求,明显是手机号码登录的意思,点开它:

Here Insert Picture Description
参数里面的倒数第二个是刚才收到的手机验证码,最后一个就是我们刚才模拟发送验证码请求时响应返回的值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) 模拟输入地址,获取必要参数

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

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

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

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

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

Here Insert Picture Description

再看一下【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请求里:

Here Insert Picture Description

然后去【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()



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

发布了16 篇原创文章 · 获赞 113 · 访问量 4890

Guess you like

Origin blog.csdn.net/qq_43280818/article/details/97614037