使用Requests库来进行爬虫的方式

Python
296
0
0
2023-06-19
标签   Python爬虫
目录
  • 使用
  • 各种请求方式
  • 基本get请求
  • 基本写法
  • 带参数get
  • 解析json
  • 获取二进制数据
  • 添加headers
  • 基本POST请求
  • 响应
  • response属性
  • 状态码判断
  • 高级操作
  • 文件上传
  • 获取cookie
  • 会话维持
  • 证书验证
  • 代理设置
  • 超时设置
  • 认证设置
  • 异常处理

Requests是用Python编写,基于urllib,采用Apache2 Licensed开源协议的HTTP库。

它比urllib更方便,可以节约我们大量的工作,完全满足HTTP测试需求。

安装:

pip install requests

使用

实例:

import requests

response=requests.get('https://www.baidu.com')
print(type(response))
print(response.status_code)
print(type(response.text))
print(response.text)
print(response.cookies)

各种请求方式

import requests

requests.post('http://httpbin.org/post')
requests.put('http://httpbin.org/put')
requests.delete('http://httpbin.org/delete')
requests.head('http://httpbin.org/get')
requests.options('http://httpbin.org/get')

我们执行以上命令后,可以在这个网址进行验证:

http://httpbin.org 这可以作为一个测试网址,它可以反馈一些我们请求时的信息。例如:

可以查看我们请求时的ip地址。

基本get请求

基本写法

import requests

response=requests.get('http://httpbin.org/get')#用get方式发送请求并获得响应
print(response.text)#用text查看响应内容

带参数get

import requests

response=requests.get('http://httpbin.org/get?name=zhuzhu&age=')
#将参数拼接到url后面,用问号分隔,参数间用&来分隔
print(response.text)

可以看到返回的args信息中包含了我们的get参数。但是这种方法使用得不是很方便,再看下面的方式:

import requests

data={
	'name':'zhuzhu',
	'age':
}
response=requests.get('http://httpbin.org/get',params=data)
#用字典的形式传递给params参数,不需要自己写url编码
print(response.text)

得到的结果与上面的方法是一样的,但是方便了许多~

解析json

import requests

response=requests.get("http://httpbin.org/get")
print(type(response.text))
print(response.json())#把返回结果编码成一个json对象
print(type(response.json()))

这个方法在返回一些AJEX请求时是比较常用的。

获取二进制数据

在下载一些内容(图片、视频)的时候常用的一个方法。

试试看,我们想要获取一个github的图标:

import requests

response=requests.get("https://github.com/favicon.ico")
print(type(response.text),type(response.content))
print(response.text)
print(response.content)#可以使用content属性来获取二进制内容

可以看到,在响应中,text的类型是string,而content的内容是bytes,也就是二进制形式。

怎么把这个图标保存到本地呢?我们已经知道怎么获取它的二进制内容,现在只需要写入文件就可以了:

import requests

response=requests.get("https://github.com/favicon.ico")
with open('favicon.ico','wb')as f:
	f.write(response.content)
	f.close()

哈哈,成功保存在运行目录下了~

添加headers

headers在爬虫中是非常必要的,很多时候如果请求不加headers,那么你可能会被禁掉或出现服务器错误…

比如我们现在想爬取知乎上的数据,但是不加headers:

import requests
response=requests.get("https://www.zhihu.com/explore")
print(response.text)

那么就会报错,因为知乎是要识别你的浏览器信息的。

我们现在加入headers试试看(做一个浏览器的伪装),只需要向get方法传入headers参数就好了:

import requests

headers={
	'User-Agent':'Mozilla/.0(Macintosh;Intel Mac OS X 10_11_4)AppleWebKit/537.36(KHTML,like Gecko)Chrome/52.0.2743.116 Safari/537.36'
}
response=requests.get("https://www.zhihu.com/explore",headers=headers)
print(response.text)

运行结果成功返回了响应信息。

基本POST请求

直接用字典构造一个data并传入方法,就可以实现post请求了,省去了编码步骤,比起urllib方便许多:

import requests


data={'name':'zhuzhu','age':''}
response=requests.post("http://httpbin.org/post",data=data)
print(response.text)


再加入headers:

import requests


data={'name':'zhuzhu','age':''}
headers={
	'User-Agent':'Mozilla/.0(Macintosh;Intel Mac OS X 10_11_4)AppleWebKit/537.36(KHTML,like Gecko)Chrome/52.0.2743.116 Safari/537.36'
}
response=requests.post("http://httpbin.org/post",data=data,headers=headers)
print(response.json())

可以看到,返回的json形式的响应中,我们成功添加了data和headers的信息。

总结:get和post请求使用都很方便,区别只是换一下方法而已。

响应

response属性

下面列出了常用的response属性:

import requests

response=requests.get("http://www.jianshu.com")
print(type(response.status_code),response.status_code)#状态码
print(type(response.headers),response.headers)
print(type(response.cookies),response.cookies)
print(type(response.url),response.url)
print(type(response.history),response.history)

状态码判断

常见的网页状态码:

100: (‘continue’,),
101: (‘switching_protocols’,),
102: (‘processing’,),
103: (‘checkpoint’,),
122: (‘uri_too_long’, ‘request_uri_too_long’),
200: (‘ok’, ‘okay’, ‘all_ok’, ‘all_okay’, ‘all_good’, ‘\o/’, ‘✓’),
201: (‘created’,),
202: (‘accepted’,),
203: (‘non_authoritative_info’, ‘non_authoritative_information’),
204: (‘no_content’,),
205: (‘reset_content’, ‘reset’),
206: (‘partial_content’, ‘partial’),
207: (‘multi_status’, ‘multiple_status’, ‘multi_stati’, ‘multiple_stati’),
208: (‘already_reported’,),
226: (‘im_used’,),
Redirection.
300: (‘multiple_choices’,),
301: (‘moved_permanently’, ‘moved’, ‘\o-’),
302: (‘found’,),
303: (‘see_other’, ‘other’),
304: (‘not_modified’,),
305: (‘use_proxy’,),
306: (‘switch_proxy’,),
307: (‘temporary_redirect’, ‘temporary_moved’, ‘temporary’),
308: (‘permanent_redirect’,
‘resume_incomplete’, ‘resume’,), # These 2 to be removed in 3.0
Client Error.
400: (‘bad_request’, ‘bad’),
401: (‘unauthorized’,),
402: (‘payment_required’, ‘payment’),
403: (‘forbidden’,),
404: (‘not_found’, ‘-o-’),
405: (‘method_not_allowed’, ‘not_allowed’),
406: (‘not_acceptable’,),
407: (‘proxy_authentication_required’, ‘proxy_auth’, ‘proxy_authentication’),
408: (‘request_timeout’, ‘timeout’),
409: (‘conflict’,),
410: (‘gone’,),
411: (‘length_required’,),
412: (‘precondition_failed’, ‘precondition’),
413: (‘request_entity_too_large’,),
414: (‘request_uri_too_large’,),
415: (‘unsupported_media_type’, ‘unsupported_media’, ‘media_type’),
416: (‘requested_range_not_satisfiable’, ‘requested_range’, ‘range_not_satisfiable’),
417: (‘expectation_failed’,),
418: (‘im_a_teapot’, ‘teapot’, ‘i_am_a_teapot’),
421: (‘misdirected_request’,),
422: (‘unprocessable_entity’, ‘unprocessable’),
423: (‘locked’,),
424: (‘failed_dependency’, ‘dependency’),
425: (‘unordered_collection’, ‘unordered’),
426: (‘upgrade_required’, ‘upgrade’),
428: (‘precondition_required’, ‘precondition’),
429: (‘too_many_requests’, ‘too_many’),
431: (‘header_fields_too_large’, ‘fields_too_large’),
444: (‘no_response’, ‘none’),
449: (‘retry_with’, ‘retry’),
450: (‘blocked_by_windows_parental_controls’, ‘parental_controls’),
451: (‘unavailable_for_legal_reasons’, ‘legal_reasons’),
499: (‘client_closed_request’,),
Server Error.
500: (‘internal_server_error’, ‘server_error’, ‘/o\’, ‘✗’),
501: (‘not_implemented’,),
502: (‘bad_gateway’,),
503: (‘service_unavailable’, ‘unavailable’),
504: (‘gateway_timeout’,),
505: (‘http_version_not_supported’, ‘http_version’),
506: (‘variant_also_negotiates’,),
507: (‘insufficient_storage’,),
509: (‘bandwidth_limit_exceeded’, ‘bandwidth’),
510: (‘not_extended’,),
511: (‘network_authentication_required’, ‘network_auth’, ‘network_authentication’),

示例:

import requests

response=requests.get("http://www.baidu.com")
exit() if not response.status_code== else print("Requests Successfully")

这说明这次请求的状态码为200.

另一种写法就是把数字200换位相应的字符串内容,详细的对应方式见上面列出的关系。

比如200对应着其中一个字符串是“ok”,我们试试:

import requests

response=requests.get("http://www.baidu.com")
exit() if not response.status_code==requests.codes.ok else print("Requests Successfully")

可以看到效果是一样的,可以根据实际情况选用。

高级操作

文件上传

import requests

files={'file':open('favicon.ico','rb')}
#通过files参数传入post方法中,实现文件的上传
response=requests.post("http://httpbin.org/post",files=files)
print(response.text)

这样通过post请求,我们就完成了文件的上传,下图file显示的就是文件的字节流了:

获取cookie

上面提到过,可以直接使用response.cookies就可以打印出cookie了。

实际上cookies是一个列表的形式,我们可以用for循环把每一个cookie取出来并且打印其key-value:

import requests

response=requests.get("http://www.baidu.com")
print(response.cookies)
for key,value in response.cookies.items():
	print(key+'='+value)

如上图,非常方便地获取到了cookie信息。这比起urllib可要方便不少~

会话维持

基本上为了实现“模拟登录”的功能。

来看例子:

import requests

requests.get('http://httpbin.org/cookies/set/number/')
#通过cookies/set方法来设置cookie
response=requests.get('http://httpbin.org/cookies')
print(response.text)

咦,cookies为空,和我们想象的不太一样。这是因为上面那段代码中发起了两次get请求,相当于两个浏览器,相互独立,所以第二次get并不能得到第一次的cookie。

那么需要采用下面的方法,通过声明Session对象来发起两次get请求,视为一个浏览器中进行的操作:

import requests

s=requests.Session()
s.get('http://httpbin.org/cookies/set/number/')
#通过cookies/set方法来设置cookie
response=s.get('http://httpbin.org/cookies')
print(response.text)

这回就成功了~

这个方法是比较常用的,用来模拟一个登录会话并维持之,这样就可以获取登录后的页面了。

证书验证

如果我们要爬取的是一个https协议的网站,那么网站首先会检查证书是否是合法的,若非法,会直接抛出SSLError错误。如果要避免这种错误的话,可以把这个参数:verify设置为False就可以了(默认是True)。

先看未设置的:

import requests
response=requests.get('https://www..cn')
print(response.status_code)

抛出了SSLError错误。

再看设置过的:

import requests


response=requests.get('https://www..cn',verify=False)#把verify参数置否
print(response.status_code)

如此就返回了200的状态码,说明这个请求是正常的,没有进行证书认证。

但是仍然会有警告信息,提示你最好加上证书验证。那么怎么消除这个警告信息呢?

可以从原生包中导入urllib3并使用其中的禁用警告这个方法:

import requests
from requests.packages import urllib
urllib.disable_warnings()#禁用警告信息


response=requests.get('https://www..cn',verify=False)
print(response.status_code)

这样就不会有警告信息了。

怎么手动添加证书呢?

示例:通过cert来指定本地证书

import requests

response=requests.get('https://www..cn',cert=('/path/server.crt','/path/key'))
print(response.status_code)

但由于我这儿没有本地证书,就不进行演示了。

代理设置

可以通过字典形式构造一个参数,字典里是你已经开通的代理ip。再把参数传入get方法即可。

import requests

proxies={
    "http":"http://.0.0.1:9743",
    "https":"https://.0.0.1:9743"
}

response=requests.get("https://www.taobao.com",proxies=proxies)
print(response.status_code)

如果代理需要用户名和密码的时候怎么办呢?

我们可以在代理的url前面直接传一个user:password,后面加个@符号,这样我们就能传入用户名和密码这个认证信息了:

proxies={
    "http":"http://uesr:password@.0.0.1:9743/",    
}

那如果代理方式不是https,而是一个socks类型的呢?

首先需要安装,在命令行执行(windows环境下):

pip install request[socks]

安装之后就可以使用这种形式的代理了。

import requests

proxies={
    "http":"sock://127.0.0.1:9743",
    "https":"socks://127.0.0.1:9743"
}

response=requests.get("https://www.taobao.com",proxies=proxies)
print(response.status_code)

超时设置

import requests

response=requests.get("https://www.taobao.com",timeout=)
#设置一个时间限制,必须在秒内得到应答
print(response.status_code)

如果时间超出了限制,就会抛出异常。怎么捕获这个异常呢?

import requests
from requests.exceptions import ReadTimeout

try:
    response=requests.get("https://httpbin.org/get",timeout=.5)
    print(response.status_code)
except ReadTimeout:
    print('Timeout')

成功捕获了这个异常,并进行处理(报信息)。

认证设置

有的网站在访问时需要输入用户名和密码,输入之后才能看到网站的内容。

如果遇到这种网站,我们可以通过auth参数,把用户名和密码传入。

import requests
from requests.auth import HTTPBasicAuth

r=requests.get('http://.27.34.24:9001',auth=HTTPBasicAuth('user','123'))
#通过auth参数传入。
print(r.status_code)

这样就可以完成一个正常的请求,如果把auth参数去掉,那么就会返回401参数(请求被禁止)。

异常处理

异常处理的部分还是比较重要的,它可以保证你的爬虫不间断地运行。

原则还是先捕获子类异常,再捕捉父类异常(RequestException)。

import requests
from requests.exceptions import ReadTimeout,HTTPError,RequestException
try:
	response=requests.get('http://httpbin.org/get',timeout=.5)
	print(response.status_code)
except ReadTimeout:#捕获超时异常
	print('Timeout')
except HTTPError:#捕获HTTP异常
	print('Http error')
except ConnectionError:#捕获连接异常
	print('Connection error')
except RequestException:#捕获父类异常
	print('Error')