python学习笔记及作业(post请求,request的高级用法,selenium)
1.post请求
get请求与post请求的区别
从网上找到很好的解释:
一.在我大万维网世界中,TCP就像汽车,我们用TCP来运输数据,它很可靠,从来不会发生丢件少件的现象。但是如果路上跑的全是看起来一模一样的汽车,那这个世界看起来是一团混乱,送急件的汽车可能被前面满载货物的汽车拦堵在路上,整个交通系统一定会瘫痪。为了避免这种情况发生,交通规则HTTP诞生了。HTTP给汽车运输设定了好几个服务类别,有GET, POST, PUT, DELETE等等,HTTP规定,当执行GET请求的时候,要给汽车贴上GET的标签(设置method为GET),而且要求把传送的数据放在车顶上(url中)以方便记录。如果是POST请求,就要在车上贴上POST的标签,并把货物放在车厢里。当然,你也可以在GET的时候往车厢内偷偷藏点货物,但是这是很不光彩;也可以在POST的时候在车顶上也放一些数据,让人觉得傻乎乎的。HTTP只是个行为准则,而TCP才是GET和POST怎么实现的基本。
二.在我大万维网世界中,还有另一个重要的角色:运输公司。不同的浏览器(发起http请求)和服务器(接受http请求)就是不同的运输公司。 虽然理论上,你可以在车顶上无限的堆货物(url中无限加参数)。但是运输公司可不傻,装货和卸货也是有很大成本的,他们会限制单次运输量来控制风险,数据量太大对浏览器和服务器都是很大负担。业界不成文的规定是,(大多数)浏览器通常都会限制url长度在2K个字节,而(大多数)服务器最多处理64K大小的url。超过的部分,恕不处理。如果你用GET服务,在request body偷偷藏了数据,不同服务器的处理方式也是不同的,有些服务器会帮你卸货,读出数据,有些服务器直接忽略,所以,虽然GET可以带request body,也不能保证一定能被接收到哦。
GET和POST本质上就是TCP链接,并无差别。但是由于HTTP的规定和浏览器/服务器的限制,导致他们在应用过程中体现出一些不同。
三.GET和POST还有一个重大区别,简单的说:
GET产生一个TCP数据包;POST产生两个TCP数据包。
长的说:
对于GET方式的请求,浏览器会把http header和data一并发送出去,服务器响应200(返回数据);
而对于POST,浏览器先发送header,服务器响应100 continue,浏览器再发送data,服务器响应200 ok(返回数据)。
也就是说,GET只需要汽车跑一趟就把货送到了,而POST得跑两趟,第一趟,先去和服务器打个招呼“嗨,我等下要送一批货来,你们打开门迎接我”,然后再回头把货送过去。
因为POST需要两步,时间上消耗的要多一点,看起来GET比POST更有效。因此Yahoo团队有推荐用GET替换POST来优化网站性能。但这是一个坑!跳入需谨慎。为什么?
1. GET与POST都有自己的语义,不能随便混用。
2. 据研究,在网络环境好的情况下,发一次包的时间和发两次包的时间差别基本可以无视。而在网络环境差的情况下,两次包的TCP在验证数据包完整性上,有非常大的优点。
3. 并不是所有浏览器都会在POST中发送两次包,Firefox就只发送一次。
'''''' ''' post请求登陆github ''' import requests import re # 一 访问login页获取token信息 ''' 请求url: https://github.com/login 请求方式: GET 响应头: Set-Cookie 请求头: Cookie User-Agent ''' headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' } response = requests.get(url='https://github.com/login', headers=headers) # print(response.text) # 把login页返回的cookies信息转换成字典 login_cookies = response.cookies.get_dict() authenticity_token = re.findall('<input type="hidden" name="authenticity_token" value="(.*?)" />', response.text, re.S)[0] print(authenticity_token) # 二 往sessionurl发送POST请求 ''' 请求url: https://github.com/session 请求方式: POST 请求头: # 上一次请求从哪里来 Referer: https://github.com/login Cookie:... User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36 请求体: 只有POST请求才会有请求体。 commit: Sign in utf8: ✓ authenticity_token: VX79esFc0YPdR1UFzUM/6MTRZOlYQ0btF5k2/x7uZea0x2E6W4bmRpwHsaCBN+096PaWNkcQjJOsyUzUqsAhIw== LLWlTr0qLcYC74hn7OI7IlyeB9rZei9737Lqtzz0sKTgY7Js7pUUhZ6bNC6lCkS+OHfVukkbTejjd0BnjPvGUg== login: tankjam1 password: ***** webauthn-support: unsupported ''' # 拼接请求头信息 headers2 = { 'Referer': 'https://github.com/login', 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36', } # 拼接请求体信息 form_data = { "commit": "Sign in", "utf8": "✓", "authenticity_token": authenticity_token, "login": "tankjam", "password": "kermit46709394", "webauthn-support": "unsupported", } # 往session地址发送post请求 # 携带请求头、请求体、login页的cookies信息 response2 = requests.post(url='https://github.com/session', data=form_data, headers=headers2, cookies=login_cookies) print(response2.status_code) # print(response2.text) with open('github.html', 'w', encoding='utf-8') as f: f.write(response2.text)
2.request的高级用法
import requests response=requests.get('https://www.baidu.com/') # reponse响应 # 获取响应状态码 print(response.status_code) # 获取url地址 print(response.url ) # 获取文本 print(response.text) # 获取二进制流 print(response.content) # 获取页面请求头信息 print(response.headers) # 上一次跳转的地址 print(response.history) # 返回cookie字典,返回cookies对象 # 获取cookies信息 print(response.cookies) # 获取cookies信息转换成字典 print(response.cookies.get_dic()) # 获取cookies信息转换成字典 print(response.cookies.items()) # 字符编码 print(response.encoding) response.encoding='utf-8' print(response.elapsed) # 生成器 # 往音频地址发送get请求 import requests # https=http+ssl(携带安全认证证书) # ssl是全世界的安全认证中心 requests.get(url='https://xiaohuar.com',verify=True) # 方法一:True 代表携带证书 print() # 超时设置 import requests response=requests.get('https://www.baidu.com/',timeout=0.1) print(response.status_code) # 代理使用 # 伪代码 import requests proxies={ # 带用户名密码的代理,@符号前是用户名与密码 'http':'http://tank:123@localhost:9527', 'http':'http://localhost:9527', 'https':'https://localhost:9527', } response=requests.get('https://www.12306.cn', proxies=proxies) print(response.status_code) # 免费代理西刺代理 # http://ipip.net # 花生代理 # 加密方式与用户体验是挂钩的 # 认证方式 # # 6.上传文件 import requests # 上传文本文件 files1 = {'file': open('user.txt', 'rb')} response = requests.post('http://httpbin.org/post', files=files1) print(response.status_code) # 200 print(response.text) # 200 # # 上传图片文件 files2 = {'jpg': open('35mm-aerial-aerial-shot-1105766.jpg', 'rb')} response = requests.post('http://httpbin.org/post', files=files2) print(response.status_code) # 200 print(response.text) # 200
3.selenium模块
超级无敌好用,用来模拟人操作浏览器。
''' selenium模块讲解 一、什么是selenium 最初是一个自动化测试工具,selenium会模拟浏览器以及人的行为帮我们 给网站发送JS请求,跳过登录方式 request不可以自动执行JS代码 浏览器会帮我们的再次发送异步请求自动执行JS代码 二、为什么要使用? 1.优点: 使用requests模块登录需要分析大量的复杂通信流程,使用selenium可以轻松跳过登录验证 2.缺点: 要驱动浏览器,浏览器会加载css,js,图片。。数据等所有的代码,会使得爬取效率低。 三、如何使用 1.首先需要下载selenium模块,方法和下载requests模块相同 在命令行中输入:pip3 install -i https://pypi.tuna.tsinghua.edu.cn/simple selenium 2.下载驱动器 ''' #selenium第一次 # webdriver是用来驱动浏览器的 # from selenium.webdriver import ActionChains 调用得到一个动作链对象,破解滑动验证码的时候用的,可以拖动图片 from selenium import webdriver # 用来驱动浏览器的 from selenium.webdriver import ActionChains # 破解滑动验证码的时候用的 可以拖动图片 from selenium.webdriver.common.by import By # 按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys # 键盘按键操作 from selenium.webdriver.support import expected_conditions as EC # 和下面WebDriverWait一起用的 from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素 from selenium import webdriver import time # 通过谷歌浏览器驱动打开谷歌浏览器 # 绝对路径有可能有.exe,有可能没有 # 驱动浏览器的一种方式 chrome=webdriver.Chrome(r'D:\360安全浏览器下载\chromedriver_win32\chromedriver') # 驱动浏览器的另一种方式,将chromedriver.exe放入到python解释器的scipt文件中,;之后还要进行环境变量的配置。 # 往博客园主页发送get请求 try: # chrome.get('https://www.cnblogs.com/') # 访问百度 # chrome是一个驱动对象,里面包含其他函数 # 参数1:驱动对象。参数2:等待 wait=WebDriverWait(chrome,10) chrome.get('https://www.baidu.com/') # 查找input输入框 #!!!!!!注意!!!!!EC.presence_of_element_located((By.ID,"kw"))里面是写的元组, #参数1.查找属性的方式,参数2:属性的名字 input_tag=wait.until(EC.presence_of_element_located((By.ID,"kw")))# kw是id的属性 # 3.搜索一拳超人 input_tag.send_keys('一拳超人') # 4.按键盘回车键 input_tag.send_keys(Keys.EQUALS) time.sleep(20) # 无论发生什么异常都会关闭浏览器 finally: # 关闭浏览器 chrome.close()
4.selenium之基本选择器
注意:所找属性要是唯一的,一般来说首选id
from selenium import webdriver # 用来驱动浏览器的 import time # 获取驱动对象 driver=webdriver.Chrome() try: # 显示等待:等待某个元素加载 # 参数1:驱动对象,参数2:等待时间 # wait=WebDriverWait(chrome,10) driver.get('https://china.nba.com/') # 隐式等待:等待页面所有元素加载完成 # 等待加载完成后,从加载好的标签里查找,每次查找会等待10秒,如果找不到就下一个 driver.implicitly_wait(10) news_tag=driver.find_element_by_class_name('nav-news') print(news_tag) time.sleep(10) finally: driver.close() ''' ===============所有方法=================== element是查找一个标签 elements是查找所有标签 1、find_element_by_link_text 通过链接文本去找 2、find_element_by_id 通过id去找 3、find_element_by_class_name 4、find_element_by_partial_link_text 5、find_element_by_name 6、find_element_by_css_selector 7、find_element_by_tag_name ''' # 1.以文本作为标识 try: # 显示等待:等待某个元素加载 # 参数1:驱动对象,参数2:等待时间 # wait=WebDriverWait(chrome,10) driver.get('https://baidu.com/') driver.implicitly_wait(10) send_tag=driver.find_element_by_link_text('登录') send_tag.click() # 隐式等待:等待页面所有元素加载完成 # 等待加载完成后,从加载好的标签里查找,每次查找会等待10秒,如果找不到就下一个 finally: driver.close() # 2.通过局部文本查找标识 try: # 显示等待:等待某个元素加载 # 参数1:驱动对象,参数2:等待时间 # wait=WebDriverWait(chrome,10) driver.get('https://baidu.com/') driver.implicitly_wait(10) login_button = driver.find_element_by_partial_link_text('登') login_button.click() # 隐式等待:等待页面所有元素加载完成 # 等待加载完成后,从加载好的标签里查找,每次查找会等待10秒,如果找不到就下一个 finally: driver.close() # 3.通过class来找 try: # 显示等待:等待某个元素加载 # 参数1:驱动对象,参数2:等待时间 # wait=WebDriverWait(chrome,10) driver.get('https://baidu.com/') driver.implicitly_wait(10) login_tag1 = driver.find_element_by_class_name('tang-pass-footerBarULogin') login_button.click() time.sleep(1) # 隐式等待:等待页面所有元素加载完成 # 等待加载完成后,从加载好的标签里查找,每次查找会等待10秒,如果找不到就下一个 finally: driver.close() # 4.通过name属性名查找 try: driver.get('https://baidu.com/') driver.implicitly_wait(10) username = driver.find_element_by_class_name('useName') username.send_keys('*******') time.sleep(1) finally: driver.close() # 5.通过id属性查找 try: driver.get('https://baidu.com/') driver.implicitly_wait(10) username = driver.find_element_by_class_name('useName') username.send_keys('*******') time.sleep(1) finally: driver.close() # 6.通过属性选择器查找 try: driver.get('https://baidu.com/') driver.implicitly_wait(10) login_submit = driver.find_element_by_css_selector('#TANGRAM__PSP_10__submit') # driver.find_element_by_css_selector('.pass-button-submit') login_submit.click() time.sleep(1) finally: driver.close() # 7、find_element_by_tag_name 根据标签名称查找标签 try: driver.get('https://baidu.com/') driver.implicitly_wait(10) div = driver.find_element_by_tag_name('div') print(div.tag_name) time.sleep(1) finally: driver.close()
5.京东实例
# 标签中首选id # 目的就是查找唯一的属性,来定位 from selenium import webdriver # 用来驱动浏览器的 from selenium.webdriver import ActionChains # 破解滑动验证码的时候用的 可以拖动图片 from selenium.webdriver.common.by import By # 按照什么方式查找,By.ID,By.CSS_SELECTOR from selenium.webdriver.common.keys import Keys # 键盘按键操作 from selenium.webdriver.support import expected_conditions as EC # 和下面WebDriverWait一起用的 from selenium.webdriver.support.wait import WebDriverWait # 等待页面加载某些元素 from selenium import webdriver import time # 通过谷歌浏览器驱动打开谷歌浏览器 # 绝对路径有可能有.exe,有可能没有 # 驱动浏览器的一种方式 chrome=webdriver.Chrome(r'D:\360安全浏览器下载\chromedriver_win32\chromedriver') # 驱动浏览器的另一种方式,将chromedriver.exe放入到python解释器的scipt文件中,;之后还要进行环境变量的配置。 # 往博客园主页发送get请求 try: # chrome.get('https://www.cnblogs.com/') # 访问百度 # chrome是一个驱动对象,里面包含其他函数 # 参数1:驱动对象。参数2:等待 wait=WebDriverWait(chrome,10) chrome.get('https://www.jd.com/') # 查找input输入框 #!!!!!!注意!!!!!EC.presence_of_element_located((By.ID,"kw"))里面是写的元组, #参数1.查找属性的方式,参数2:属性的名字 input_tag=wait.until(EC.presence_of_element_located((By.ID,"key")))# kw是id的属性 # 3.搜索一拳超人 input_tag.send_keys('唐诗三百首') # 4.按键盘回车键 search_button=wait.until(EC.presence_of_element_located((By.CLASS_NAME,"button"))) search_button.click() time.sleep(20) # 无论发生什么异常都会关闭浏览器 finally: # 关闭浏览器 chrome.close()