【request】使用request库,实现更加方便的爬取网页

本文主要参考北航硕士崔庆才的《Python3网络爬虫开发实战》。

了解了 urllib 的基本用法,但是其中确实有不方便的地方,比如处理网页验证和 Cookie 时,需要写 Opener 和 Handler 来处理。另外我们要实现 POST、PUT 等请求时写法也不太方便。

为了更加方便地实现这些操作,就有了更为强大的库 requests,有了它,Cookie、登录验证、代理设置等操作都更加简单。requests的官方文档

1 基本用法

urllib 库中的 urlopen 方法实际上是以 GET 方式请求网页,而 requests 中相应的方法就是 get() 方法。

import requests

r = requests.get('https://www.baidu.com/')
print(type(r))
print(r.status_code)
print(type(r.text))
print(r.text[:100])
print(r.cookies)

调用 get 方法实现与 urlopen 相同的操作,得到一个 Response 对象,然后分别输出了 Response 的类型、状态码、响应体的类型、内容以及 Cookie。

使用其他请求的代码也比较简单,如下:

import requests

r = requests.get('https://httpbin.org/get')
r = requests.post('https://httpbin.org/post')
r = requests.put('https://httpbin.org/put')
r = requests.delete('https://httpbin.org/delete')
r = requests.patch('https://httpbin.org/patch')

2 GET请求

2.1 添加额外信息

对于GET请求,如果要添加额外的信息:

https://httpbin.org/get?name=germey&age=25

也可选择使用params这个参数,将信息存入字典

import requests

data = {
    'name': 'germey',
    'age': 25
}
r = requests.get('https://httpbin.org/get', params=data)
print(r.text)
# 返回get请求的相关信息

网页的返回类型实际上是 str 类型,但是它很特殊,是 JSON 格式的。所以,如果想直接解析返回结果,得到一个 JSON 格式的数据的话,可以直接调用 json 方法。

print(r.json())

调用 json 方法,就可以将返回结果是 JSON 格式的字符串转化为字典。需要注意的是,如果返回结果不是 JSON 格式,便会出现解析错误,抛出 json.decoder.JSONDecodeError 异常。

2.2 抓取网页

上面的请求链接返回的是 JSON 形式的字符串,那么如果请求普通的网页,则肯定能获得相应的内容了。

import requests
import re

r = requests.get('https://ssr1.scrape.center/')
# print(r.text) # 打印html源代码
pattern = re.compile('(.*?)', re.S)    # 运用正则表达式进行匹配
titles = re.findall(pattern, r.text)
print(titles)   # 打印匹配出的文本内容

使用正则表达式匹配出所有的问题内容。

2.3 抓取二进制数据

图片、音频、视频这些文件本质上都是由二进制码组成的,由于有特定的保存格式和对应的解析方式,我们才可以看到这些形形色色的多媒体。所以,想要抓取它们,就要拿到它们的二进制数据。

import requests

r = requests.get('https://scrape.center/favicon.ico')
print(r.text)
print()
print(r.content)

部分结果如下图所示:

【request】使用request库,实现更加方便的爬取网页_第1张图片

前者出现了乱码,后者结果前带有一个 b,这代表是 bytes 类型的数据。由于图片是二进制数据,所以前者在打印时转化为 str 类型,也就是图片直接转化为字符串,这理所当然会出现乱码。

我们可以将刚才提取到的信息保存下来,代码如下:

r = requests.get('https://scrape.center/favicon.ico')
with open('favicon.ico', 'wb') as f:
# open方法的第一个参数是文件名称,第二个参数代表以二进制写的形式打开
    f.write(r.content)

运行结束以后,我们就可在当前工作目录下看到一个名为favicon.ico的图标(文件)。

2.4 添加headers

如何在request库的函数中设置headers?

headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
}
r = requests.get('https://ssr1.scrape.center/', headers=headers)
print(r.text)

3 POST请求

使用request实现POST请求

data = {'name': 'germey', 'age': '25'}
r = requests.post("https://httpbin.org/post", data=data)
print(r.text)

4 响应

发送请求后,得到的自然就是响应。在上面的实例中,我们使用 text 和 content 获取了响应的内容。此外,还有很多属性和方法可以用来获取其他信息,比如状态码、响应头、Cookie 等。示例如下:

r = requests.get('https://ssr1.scrape.center/')
print(type(r.status_code), r.status_code)
print(type(r.headers), r.headers)
print(type(r.cookies), r.cookies)
print(type(r.url), r.url)
print(type(r.history), r.history)

这里分别打印输出 status_code 属性得到状态码,输出 headers 属性得到响应头,输出 cookies 属性得到 Cookie,输出 url 属性得到 URL,输出 history 属性得到请求历史。

5 高级用法

(1)文件上传

requests 可以模拟提交一些数据。

files = {'file': open('favicon.ico', 'rb')}
r = requests.post('https://httpbin.org/post', files=files)
print(r.text)

使用前面保存的文件favicon.ico,用它来模拟文件上传。

(2)Cookie设置

通过request,可以迅速获取和设置Cookie。

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

首先调用 cookies 属性即可成功得到 Cookie,可以发现它是 RequestCookieJar 类型。然后用 items 方法将其转化为元组组成的列表,遍历输出每一个 Cookie 条目的名称和值,实现 Cookie 的遍历解析。

我们也可以复制网站中的cookie,将其设置到Headers里面,然后发送请求。

headers = {
    'Cookie': '_octo=GH1.1.1849343058.1576602081; _ga=GA1.2.90460451.1576602111; __Host-user_session_same_site=nbDv62kHNjp4N5KyQNYZ208waeqsmNgxFnFC88rnV7gTYQw_; _device_id=a7ca73be0e8f1a81d1e2ebb5349f9075; user_session=nbDv62kHNjp4N5KyQNYZ208waeqsmNgxFnFC88rnV7gTYQw_; logged_in=yes; dotcom_user=Germey; tz=Asia%2FShanghai; has_recent_activity=1; _gat=1; _gh_sess=your_session_info',
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36',
}
r = requests.get('https://github.com/', headers=headers)
print(r.text)

我们用 Cookie 就成功模拟了登录状态,这样我们就能爬取登录之后才能看到的页面了。

我们也可以通过 cookies 参数来设置 Cookie 的信息,这里我们可以构造一个 RequestsCookieJar 对象,然后把刚才复制的 Cookie 处理下并赋值。

jar = requests.cookies.RequestsCookieJar()
headers = {
    'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53.0.2785.116 Safari/537.36'
}
for cookie in cookies.split(';'):
    key, value = cookie.split('=', 1)
    jar.set(key, value)
r = requests.get('https://github.com/', cookies=jar, headers=headers)
print(r.text)

(3)Session维持

如果直接利用 get 或 post 等方法的确可以做到模拟网页的请求,但是这实际上是相当于不同的 Session,也就是说相当于你用了两个浏览器打开了不同的页面。

利用Session对象,我们可以方便地维护一个 Session,而且不用担心 Cookie 的问题,它会帮我们自动处理好。

这里请求了一个测试网址 https://httpbin.org/cookies/set/number/123456789。请求这个网址时,可以设置一个 Cookie 条目,名称叫作 number,内容是 123456789,随后又请求了 https://httpbin.org/cookies,此网址可以获取当前的 Cookie 信息。

s = requests.Session()
s.get('https://httpbin.org/cookies/set/number/123456789')
r = s.get('https://httpbin.org/cookies')
print(r.text)

(4)SSL证书验证

现在很多网站都要求使用 HTTPS 协议,但是有些网站可能并没有设置好 HTTPS 证书,或者网站的 HTTPS 证书可能并不被 CA 机构认可,这时候,这些网站可能就会出现 SSL 证书错误的提示。

如果抛出了 SSLError 错误,原因就是因为我们请求的 URL 的证书是无效的。

我们可以使用 verify 参数控制是否验证证书,如果将其设置为 False,在请求时就不会再验证证书是否有效。如果不加 verify 参数的话,默认值是 True,会自动验证。

response = requests.get('https://ssr2.scrape.center/', verify=False)
print(response.status_code)

(5)超时设置

为了防止服务器不能及时响应,应该设置一个超时时间,即超过了这个时间还没有得到响应,那就报错。这需要用到 timeout 参数。这个时间的计算是发出请求到服务器返回响应的时间。

r = requests.get('https://httpbin.org/get', timeout=1)
print(r.status_code)

实际上,请求分为两个阶段,即连接(connect)和读取(read)。上面设置的 timeout 将用作连接和读取这二者的 timeout 总和。如果要分别指定,就可以传入一个元组:

r = requests.get('https://httpbin.org/get', timeout=(5, 30))

如果想永久等待,可以直接将 timeout 设置为 None,或者不设置直接留空,因为默认是 None。或直接不加参数。

(6)身份认证

request自带身份认证功能,通过auth参数设置

# 示例网站的用户名和密码都是 admin
r = requests.get('https://ssr3.scrape.center/', auth=('admin', 'admin'))
print(r.status_code)

(7)代理设置

为了防止大规模爬取被拒绝,需要设置代理。

proxies = {
  'http': 'http://10.10.10.10:1080',
  'https': 'http://10.10.10.10:1080',
}
requests.get('https://httpbin.org/get', proxies=proxies)

直接运行这个实例可能不行,因为这个代理可能是无效的,可以直接搜索寻找有效的代理并替换试验一下。

除了基本的 HTTP 代理外,requests 还支持 SOCKS 协议的代理。

(8)Prepared Request

requests 在发送请求的时候,是在内部构造了一个 Request 对象,并给这个对象赋予了各种参数,包括 url、headers、data 等等,然后直接把这个 Request 对象发送出去,请求成功后会再得到一个 Response 对象,再解析即可。

这个Request实际上就是Prepared Request。不使用get方法的话,稍微“原始”一点的代码如下所示:

s = Session()
req = Request('POST', url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)

你可能感兴趣的:(python基础,json,python,前端,1024程序员节)