爬虫-笔记

1. requests hook

requests中的hook机制, 让我们用来请求得到响应之后去做一些自定义的操作比如打印某些信息、修改响应内容等。具体用法见下面的例子:

import requests

# 钩子函数1
def print_url(r, *args, **kwargs):
    print("raw_url "+r.url)
# 钩子函数2
def change_url(r, *args, **kwargs):
    r.url = 'http://change.url'
    print("changed_url "+r.url)
    return r  # 其实没有这句话,也可以修改r.url,因为r是response对象而非普通数值,但requests官方似乎误认为回调函数一定要有return才能替换传入的数据

# tips: http://httpbin.org能够用于测试http请求和响应
url = 'http://httpbin.org/cookies'
response = requests.get(url, hooks=dict(response=[print_url, change_url]))
print("result_url "+response.url)

运行结果:

raw_url http://httpbin.org/cookies
changed_url http://change.url
result_url http://change.url

在例子中,定义了两个钩子函数,分别用来打印response对象中的url和修改response对象中的url。通过参数hooks=dict(response=[print_url, change_url])调用,其中response是钩子的类型(目前requests v2.22.0版本仅有这一种类型)。从运行结果中,可以看出钩子函数1和钩子函数2被顺序执行了,且达到了篡改响应结果的目的。

上述例子中,只在requests方法级别调用了一次hook,如果想要每个请求都使用hook呢?可以在requests的session对象中添加hook来让该session对象发出去的请求均带有hook(关于session的用法可移步python之requests模块-session中查看),比如:

s = requests.Session()
s.hooks.update({"response": [print_url, change_url]})
转载: https://www.cnblogs.com/zhuosanxun/p/12700191.html

2. requests session机制

http协议本身是无状态的,为了让请求之间保持状态,有了session和cookie机制。requests也提供了相应的方法去操纵它们。

requests中的session对象能够让我们跨http请求保持某些参数,即让同一个session对象发送的请求头携带某个指定的参数。当然,最常见的应用是它可以让cookie保持在后续的一串请求中。

下面,通过官方文档中的示例来了解如何使用它。

import requests

s = requests.Session()
# 第一步:发送一个请求,用于设置请求中的cookies
# tips: http://httpbin.org能够用于测试http请求和响应
s.get('http://httpbin.org/cookies/set/sessioncookie/123456789')
# 第二步:再发送一个请求,用于查看当前请求中的cookies
r = s.get("http://httpbin.org/cookies")
print(r.text)

运行结果:

{
  "cookies": {
    "sessioncookie": "123456789"
  }
}

从结果中我们可以看出,第二次请求已经携带上了第一次请求所设置的cookie,即通过session达到了保持cookie的目的。示例中创建了一个requests.Session()对象,通过该对象来进行http请求操作,该操作基本类似于requests.request(),可查看python之requests模块-request api进行了解。

由于session让请求之间具有了连贯性,那么,就有了跨请求参数和非跨请求参数的区别。即有时我想让所有请求均带有某个参数,而有时我只是想让单独的一条请求带上临时的参数。通过下面的例子来了解如何使用。

import requests

s = requests.Session()
#设置session对象的auth属性,用来作为请求的默认参数  
s.auth = ('user', 'pass')  
# 设置session的headers属性,通过update方法,将其余请求方法中的headers属性合并起来作为最终的请求方法的headers 
s.headers.update({'x-test': 'true'}) 
# 发送请求,这里没有设置auth会默认使用session对象的auth属性,这里的headers属性会与session对象的headers属性合并  
r1 = s.get('http://httpbin.org/headers', headers={'x-test2': 'true'})
print(r1.text)
# 'x-test' is sent
r2 = s.get('http://httpbin.org/headers')
print(r2.text)

运行结果:

# r1.text
{
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.22.0", 
    "X-Amzn-Trace-Id": "Root=1-5e91656f-b99f14a4d6f47f9e55a90bb4", 
    "X-Test": "true", 
    "X-Test2": "true"
  }
}
# r2.text
{
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.22.0", 
    "X-Amzn-Trace-Id": "Root=1-5e91656f-e9741db4c2ca2fd6e0628396", 
    "X-Test": "true"
  }
}

从结果中我们可以得出两条结论:

1. session可以为请求方法提供缺省数据,比如第一次请求中的{'x-test': 'true'}就是缺省数据,此时的缺省数据就是跨请求参数。
2方法级别的参数不会被跨请求保持,比如第二次请求时,没有携带headers={'x-test2': 'true'},返回的结果中也没有{'x-test2': 'true'},说明该参数没有在第一次请求后被保持住。
转载:https://www.cnblogs.com/zhuosanxun/p/12679121.html	

2.2 requests 内置参数和cookie使用

# 设置requests请求重试次数为5,默认为2
requests.DEFAULT_RETRIES = 5
request = requests.session()
# 禁止使用页面缓存 
request.keep_alive = False
resp = request.post(url='http://222.173.24.186:9090/', data=data,headers=headers)
cookies = {}
print(request.cookies.items())
for cookie in request.cookies:
    cookies[cookie.name] = cookie.value
resp2 = request.get(url='http://222.173.24.186:9090/web_flowls/flow_pur_queryls.aspx', headers=headers, cookies=cookies)
# pyquery使用案例
from pyquery import PyQuery as pq
# doc3 = pq(resp3.text)
# '__VIEWSTATEGENERATOR' : doc('#__VIEWSTATEGENERATOR').val(),
# '__VIEWSTATE' : doc('#__VIEWSTATE').val(),
# '__EVENTVALIDATION' : doc('#__EVENTVALIDATION').val(),

3. requests history响应查看

response.history返回包含请求(URL)历史的响应对象列表。本质上,它以响应列表的形式显示请求如何到达目标。

import requests module 
import requests 

response = requests.get('https://geeksforgeeks.org') 
print(response) 
print(response.history)
print(response.history[0].headers)
转载:https://vimsky.com/examples/usage/response-history-python-requests.html

4. requtests cookies替换

# 一个是把cookie先写成字典形式,然后把字典转换为cookiejar
s = requests.Session()  # 开启一个会话Session
cookie_dict={'49BAC005-7D5B-4231-8CEA-16939BEACD67': 'cktest001',   # 从chrome浏览器中取到的cookie值
             'JSESSIONID':'F4FFF69B8XXXXXXC8DCB4C061C0',
             'JSESSIONIDSSO':'9D49C76FD6XXXXXF294242B44A'
             }
# requests.utils.cookiejar_from_dict 转换为cookiejar
# requests.utils.dict_from_cookiejar 转换位字典
s.cookies = requests.utils.cookiejar_from_dict(cookie_dict, cookiejar=None, overwrite=True)  # 把cookie值转换为cookiejar类型,然后传给Session注意:这个方法会替换掉原有的cookies
# 追加cookies
s = requests.Session()  # 开启一个会话Session
jar = requests.cookies.RequestsCookieJar()   # 创建一个Cookie Jar对象
jar.set('49BAC005-7D5B-4231-8CEA-1XXXXBEACD67','cktXXXX001')  # 向Cookie Jar对象中添加cookie值
jar.set('JSESSIONID','F4FFF69B8CXXXX80F0C8DCB4C061C0')
jar.set('JSESSIONIDSSO','9D49C7XXXX448FDF5B0F294242B44A')
s.cookies.update(jar)  # 把cookies追加到Session中

5.1 seleniun 使用cookie

用账号密码模拟登录。拿到cookie,保存在txt文件,这个要注意,我们获取的cookie是字典格式,我们需要使用cookies = json.dumps(cookies)转换为字符串格式再保存入txt文件,

from selenium import webdriver
import time

driver = webdriver.Firefox()
driver.get("https://www.baidu.com/")
time.sleep(3)
driver.find_element("userName").send_keys("1356046")
driver.find_element("password").send_keys("x9122")
driver.find_element("linkText","登录").click()

cookies = driver.get_cookies()
print (type(cookies))
# print ("".join(cookies))
f1 = open('cookie.txt', 'w')
f1.write(json.dumps(cookies))
f1.close

然后到cookie.txt文件里看cookie格式是否正确,键值都是用双引号”“,如下
{“a”:1,”b”:2,”c”:3,”d”:4,”e”:5}
如果是
{u’a’: 1, u’c’: 3, u’b’: 2, u’e’: 5, u’d’: 4}
说明格式还没转好
然后又从文件取出cookie,因为取出的时候是字符串形式,然后通过cookie =json.loads(cookie)转为字典,因为取出的cookie,使用通过循环add到driver,然后刷新一下driver就可以了

f1 = open('cookie.txt')
cookie = f1.read()
cookie =json.loads(cookie)
for c in cookie:
    driver.add_cookie(cookie_dict=cookies)
# # 刷新页面
driver.refresh()
转载:https://blog.csdn.net/jyxmust/article/details/79393135

5.2 注意事项

1. 报错:Message: unable to set cookie
2. 报错: Message: invalid argument: missing 'name'
from selenium import webdriver

driver = webdriver.Chrome()
# name:cookie的名称 必须有
# value:cookie对应的值,动态生成的, 必须有
# domain:服务器域名
# expiry:Cookie有效终止日期
# path:Path属性定义了Web服务器上哪些路径下的页面可获取服务器设置的Cookie
# httpOnly:防脚本攻击
# secure:在Cookie中标记该变量,表明只有当浏览器和Web Server之间的通信协议为加密认证协议时# 
# {'domain': '.gonggaotong.net', 'httpOnly': False, 'name': 'Hm_lpvt_5aed315e6cf23667dff3f1224c5dcb60', 'path': '/', 'secure': False, 'value': '1642657344'}
# 并且每一个cookie参数都要有name和value等字段
cookies = {'value': 'think%3A%7B%22username%210293%31628193MDAwMDAwMLOGpZaIudFqhc6Gl7LQetmZtmfOk2RhbQ%22%2C%22expire%sfdaaswMDAwMDAwMLOGud6Gqb-whbiCmLOmdZ4%22%2C%22token%22%3A%22MDAwMDAwMDAwMMurrpWavLehhs1-3LLfgduEt4OWepuo123456123KZq6HQxtOK0ZCme5p-q6iZu2yrn4uNhJ3KedDYk7ivboS4it6910926YW0%22%7D',
           'name': 'ketangpai_home_remember'}
# 在设置cookie之前必须先访问这个网站,否则就会报错
driver.get("https://www.ketangpai.com/User/login.html")
#一旦加载网站,即使没登录,也会产生一个cookie,所以这个cookie被删除了
driver2.delete_all_cookies()
driver.add_cookie(cookie_dict=cookies)
driver.get("https://www.ketangpai.com/Main/index.html")

5.3 样例

from selenium import webdriver
import time

#driver1登录网站,获得cookie并保存
driver1 = webdriver.Chrome()
driver1.get("https://www.ketangpai.com/User/login.html")
driver1.maximize_window()
time.sleep(2)

#第一次通过send_keys向输入框发送用户名密码登录
driver1.find_element_by_xpath("//input[@name='account']").send_keys("your username")
driver1.find_element_by_xpath("//input[@name='pass']").send_keys("your password")
time.sleep(2)
driver1.find_element_by_xpath("//div[@class='padding-cont pt-login']//a[@class='auto-login fl']").click()
time.sleep(3)
driver1.find_element_by_xpath("//div[@class='padding-cont pt-login']//a[@class='btn-btn']").click()
time.sleep(6)
#用get_cookies的方法得到登录后的cookie,这个cookie是个列表,列表中两个元素都是字典,第一个是登录前的cookie,第二个是登录后的cookie
#将cookie保存在变量savedCookies中
savedCookies = driver1.get_cookies()
print(savedCookies)

#driver2得到driver1的cookie,先删除自己的所有cookie,再将driver1的cookie添加进来
driver2 = webdriver.Chrome()
#必须首先加载网站,这样selenium才知道cookie是属于哪个网站的
driver2.get("https://www.ketangpai.com/User/login.html")
#一旦加载网站,即使没登录,也会产生一个cookie,所以这个cookie被删除了
driver2.delete_all_cookies()
#遍历savedCookies中的两个元素
for cookie in savedCookies:
    #k代表着add_cookie的参数cookie_dict中的键名,这次我们要传入这5个键
    for k in {'name', 'value', 'domain', 'path', 'expiry'}:
        #cookie.keys()属于'dict_keys'类,通过list将它转化为列表
        if k not in list(cookie.keys()):
            #saveCookies中的第一个元素,由于记录的是登录前的状态,所以它没有'expiry'的键名,我们给它增加
            if k == 'expiry':
                t = time.time()
                cookie[k] = int(t)    #时间戳s
    #将每一次遍历的cookie中的这五个键名和键值添加到cookie
    driver2.add_cookie({k: cookie[k] for k in {'name', 'value', 'domain', 'path', 'expiry'}})

#加载我们想要看到的页面的url
driver2.get("https://www.ketangpai.com/Main/index.html")
#再次打印driver2的cookie
print(driver2.get_cookies())

注意:cookie有两种,一种是会话级别的,一种是有有效期的,会话级别的cookie就不能用add_cookie的方法了,因为一次会话过程(从打开浏览器到关闭浏览器,断开连接)结束后它就失效了

转载:https://www.cnblogs.com/sundahua/p/10202494.html

你可能感兴趣的:(python,爬虫,python,开发语言,后端)