测试代码
import requests
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
}
r = requests.get("http://www.baidu.com", headers=headers)
print(r.url)
# 以上代码打印结果为:https://m.baidu.com/?from=844b&vit=fps
思考:为什么打印出来的url不是请求的url呢? 想要搞清楚这个问题,就要知道requests的重定向问题。 requersts的默认情况 默认情况下,requests发送的请求除了方式为HEAD之外,其余的请求例如GET、POST等都是能自动进行重定向的 这也就是为什么上面明明访问的是http://www.baidu.com而打印出来之后是https://m.baidu.com/?from=844b&vit=fps的原因 取消自动重定向 在发送请求的时候,可以通过如下的设置,取消requests模块的自动重定向功能
requests.get(url, allow_redirects=False)
示例代码:
import requests
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
}
response = requests.get("http://www.baidu.com", headers=headers, allow_redirects=False)
print(response.status_code)
print(response.url)
默认情况下获取历史请求 通过response.history可以获取到请求的历史记录
import requests
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
}
response = requests.get("http://www.360buy.com", headers=headers)
print("历史请求过程信息:")
print(response.history)
for one_info in response.history:
print(one_info.status_code, one_info.url, one_info.headers)
print("\n\n最后一次的请求信息:")
print(response.status_code, response.url, response.headers)
在浏览网页时,可能会遇到以下这种情况: 出现这个问题的原因是:ssl证书不安全导致的。 在代码中发起请求的效果
import requests
# 网站已无法正常访问, 可参考截图...
url = "https://chinasoftinc.com/owa"
response = requests.get(url)
print(response.text)
# 当前程序报错:ssl.CertificateError...
解决方案 在代码中设置verify参数
import requests
url = "https://chinasoftinc.com/owa"
response = requests.get(url, verify=False)
print(response.text)
在爬虫中,一个请求很久没有结果,就会让整个项目的效率变得非常低。这个时候我们就需要对请求进行强制要求,让他必须在特定的时间内返回结果,否则就报错。 超时参数的使用
r = requests.get(url, timeout=3)
通过添加timeout参数,能够保证在三秒钟内返回响应,否则会报错。
import requests
# url = "https://www.baidu.com"
url = "https://www.google.com"
response = requests.get(url=url, timeout=1)
这个方法还能够拿来检测代理ip(代理会在后面讲解)的质量,如果一个代理ip在很长时间没有响应,那么添加超时之后也会报错,对应的这个ip就可以从代理ip池中删除。
使用超时参数能够加快我们整体的运行速度。但是在普通的生活中当我们使用浏览器访问网页时,如果发生速度很慢的情况,我们会做的选择是刷新页面。那么在代码中,我们是否也可以刷新请求呢? 在本小节中我们使用retrying模块来完成需求。
模块地址:https://pypi.org/project/retrying/
作用:
使用retrying模块提供的retry模块 通过装饰器的方式使用,让被装饰的函数反复执行 retry中可以传入参数stop_max_attempt_number,让函数报错后继续重新执行,达到最大执行次数的上限,如果每次都报错,整个函数报错,如果中间有一个成功,程序继续往后执行
import time
from retrying import retry
num = 1
@retry(stop_max_attempt_number=3)
def test():
global num
print("num=", num)
num += 1
time.sleep(1)
for i in 100:
print("i", i)
if __name__ == '__main__':
try:
test()
except Exception as ret:
print("产生异常...")
print(ret)
else:
print("没有异常")
retrying和requests的简单封装 实现一个发送请求的函数,每次爬虫中直接调用该函数即可实现发送请求 使用timeout实现超时报错 使用retrying模块实现重试 示例代码:
import requests
from retrying import retry
num = 1
@retry(stop_max_attempt_number=3)
def _parse_url(url):
global num
print("第%d次尝试" % num)
num += 1
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
}
# 超时的时候会报错并重试
response = requests.get(url, headers=headers, timeout=3)
# 状态码不是200,也会报错并重试
assert response.status_code == 200 # 此语句是"断言",如果assert后面的条件为True则呈现继续运行,否则抛出异常
return response
def parse_url(url):
# 进行异常捕获
try:
response = _parse_url(url)
except Exception as e:
print("产生异常:", e)
# 报错返回None
response = None
return response
if __name__ == '__main__':
url = "https://chinasoftinc.com/owa"
# url = "https://www.baidu.com"
print("----开始----")
r = parse_url(url=url)
print("----结束----", "响应内容为:", r)
当我们发送POST请求的时候,一般会携带数据,之前在学习POST时,可以通过给data赋值,从而能够完成传递form表单数据。
requests.post(url, data={"kw": "python"})
但有很多时候,要向服务器发送的是json数据,此时应该怎么办呢?
requests.post(url, json={"kw": "python"})
在请求方法中设置json参数即可。
代码示例:
import requests
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
}
response = requests.post("https://fanyi.baidu.com/sug", headers=headers, json={"kw": "python"}, timeout=3)
print("请求头是:", response.request.headers)
print("请求体是:", response.request.body)
当我们在爬取某些页面的时候,服务器往往会需要cookie,而想要得到cookie就需要先访问某个URL进行登录,服务器接收到请求之后验证用户名以及密码在登录成功的情况下会返回一个响应,这个响应的header中一般会有一个set-cookie的信息,它对应的值就是要设置的cookie信息。
虽然我们再之前可以通过requests.utils.dict_from_cookiejar(r.cookies)提取到这个响应信息中设置的新cookie,但在下一个请求中再携带这个数据的过程较为麻烦,所以requests有个高级的方式 - 会话Session
Session的作用
Session能够跨请求保持某些参数,也会在同一个Session实例发出的所有请求之间保持cookie 会话保持有两个内涵:
保存cookie,下一次请求会自动带上前一次的cookie 实现和服务端的长连接,加快请求速度
使用方法
# 1. 创建一个session实例对象
s = requests.Session()
# 2. 使用上一步创建的对象发起请求
r = s.get(url1, headers)
r = s.get(url2, headers)
r = s.get(url3, headers)
r = s.get(url4, headers)
session对象在请求了一个网站后,对方服务器设置在本地的cookie会保存在session对象中,下一次再使用session对象请求对方服务器的时候,会自动带上前一次的cookie。 代码示例:
import requests
session = requests.Session()
headers = {
"User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
}
# 发送第一个请求
response = session.get('https://www.baidu.com', headers=headers)
print("第一次请求的请求头为:", response.request.headers)
print("响应头:", response.headers)
print("设置的cookie为:", requests.utils.dict_from_cookiejar(response.cookies))
# 发送第二个请求
response = session.get("https://www.baidu.com")
print("第二次请求的请求头为:", response.request.headers)
使用代理的原因
当在爬某个网站的时候,如果对方进行了封锁例如将我们电脑的公网ip封锁了,那么也就意味着只要是这个ip发送的所有请求这个网站都不会进行响应;此时我们就可以使用代理,绕过它的封锁从而实现继续爬取数据
基本原理
在当前用户电脑中连接其他区域的电脑,每台电脑因为区域不同所以分配的ip也不相同。使用其他区域的电脑帮助我们发送想要发送的请求。
基本使用
将代理地址与端口配置成字典并使用proxies参数传递
proxies = {
"http": "http://10.10.1.10:3128",
"https": "http://10.10.1.10:1080",
}
requests.get("https://example.org", proxies=proxies)
如何获取代理
百度查询免费代理ip,但一般情况下都不太好用 付费代理:https://www.zmhttp.com/?have_open_ok=1
对于免费代理大部分都是不可用的,建议可以使用付费代理。例如:芝麻代理、快代理等等。
代理案例
import requests
# http代理
ip = "127.0.0.1"
port = 7890
proxies = {
"http": "http://%s:%d" % (ip, port),
"https": "http://%s:%d" % (ip, port)
}
# 请求头
headers = {
"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_3) AppleWebKit/537.36 "
"(KHTML, like Gecko) Chrome/86.0.4240.183 Safari/537.36"
}
url = "http://httpbin.org/ip"
response = requests.get(url=url, headers=headers, proxies=proxies, timeout=10)
print(response.text)




