Python3网络爬虫(二) -- 使用更好用的Requests爬虫库

上一章我们使用Urllib来写网络爬虫,但是我们能发现,他的功能不是很足,因为比如网页验证,处理cookies等功能需要opener和handler来实现。现在我们使用更加强大的爬虫库Requests

首先安装这个库
在urllib库中,我们使用urlopen来请求网页,但是实际上就是使用了一个GET方法来请求网页,在requests中,直接使用get()方法:

import requests
r = requests.get('https://www.baidu.com/')
print(type(r))  # requests.models.Response类型
print(r.status_code)  # 状态码
print(type(r.text))  # Response Body 的类型为一个字符串
print(r.text)
print(r.cookies)

除了使用get(),我们还可以:

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


get请求

如果要给链接传递参数:

import requests
data = {
    'name': 'germey',
    'age': 22
}
r = requests.get("http://httpbin.org/get", params=data)
print(r.text)

网页的text虽然是字符串类型,但还是json格式,所以可以直接使用json()将其转换为字典格式:

r = requests.get("http://httpbin.org/get")
print(r.json())

抓取页面例子:抓取知乎页面所有问题

import requests
import re

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://www.zhihu.com/explore", headers=headers)
pattern = re.compile('explore-feed.*?question_link.*?>(.*?)', re.S)
titles = re.findall(pattern, r.text)
print(titles)

抓取图片视频等二进制数据:

import requests
r = requests.get("https://github.com/favicon.ico")
print(r.text)
print(r.content)

第一行会出现乱码,第二行会出现byte类型数据。因为图片实际上是二进制数据,所以第一行将其直接转换为字符串会出错,那么我们如何将抓取到的图片保存下来呢?

import requests
r = requests.get("https://github.com/favicon.ico")
with open('favicon.ico', 'wb') as f:
    # wb表示以二进制的方式写入文件
    f.write(r.content)


Post请求

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

返回结果中的form部分就是提交的数据,这就能证明POST请求成功了



Response

上面我们使用了text和content来获取内容,其实还有以下属性和方法:

import requests
r = requests.get('http://www.jianshu.com')
print(type(r.status_code), r.status_code)   #状态码
print(type(r.headers), r.headers)  #请求头
print(type(r.cookies), r.cookies)  #cookies
print(type(r.url), r.url)
print(type(r.history), r.history)  #请求历史

结果如下:

 200
 {'X-Runtime': '0.006363', 'Connection': 'keep-alive', 'Content-Type': 'text/html; charset=utf-8', 'X-Content-Type-Options': 'nosniff', 'Date': 'Sat, 27 Aug 2016 17:18:51 GMT', 'Server': 'nginx', 'X-Frame-Options': 'DENY', 'Content-Encoding': 'gzip', 'Vary': 'Accept-Encoding', 'ETag': 'W/"3abda885e0e123bfde06d9b61e696159"', 'X-XSS-Protection': '1; mode=block', 'X-Request-Id': 'a8a3c4d5-f660-422f-8df9-49719dd9b5d4', 'Transfer-Encoding': 'chunked', 'Set-Cookie': 'read_mode=day; path=/, default_font=font2; path=/, _session_id=xxx; path=/; HttpOnly', 'Cache-Control': 'max-age=0, private, must-revalidate'}
 , , ]>
 http://www.jianshu.com/
 []

使用status code来判断请求是否成功:

import requests
r = requests.get('http://www.jianshu.com')
exit() if not r.status_code == requests.codes.ok else print('Request Successfully')

上面这个例子比较了返回码和内置的成功码,如果成功输出成功消息,失败则程序终止,这里requests.codes.ok得到的状态码是200,其他的为:状态码
如果想判断结果是不是404 ,则使用requests.codes.not_found



高级用法:代理,cookies…

文件上传:

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

网站返回Response,里面包含files字段,而form是空的,证明文件上传部分会有单独的Files字段来标识。

===========================================================

cookies:
urllib处理cookies的方式很复杂,但是Requests,获取和设置都非常的简单。有两种方法:
获取cookies方式:

import requests
r = requests.get('https://www.baidu.com')
print(r.cookies)
for key, value in r.cookies.items():
    print(key + '=' + value)
>>>  , ]>
	 BDORZ=27315
     __bsi=13533594356813414194_00_14_N_N_2_0303_C02F_N_N_N_0
  1. 直接复制cookies来维持登录状态
    首先登录网站,将headers里面的cookies复制下来,然后设置到headers里面发送请求:
import requests
headers = {
    'Cookie': 'q_c1=31653b264a074fc9a57816d1ea93ed8b|1474273938000|1474273938000',
    'Host': 'www.zhihu.com',
    '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://www.zhihu.com', headers=headers)
  1. 通过cookies参数来设置
    需要构造 RequestsCookieJar 对象,而且需要分割一下 Cookies
import requests

cookies = '..........'
jar = requests.cookies.RequestsCookieJar()
headers = {
    'Host': 'www.zhihu.com',
    '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('http://www.zhihu.com', cookies=jar, headers=headers)
print(r.text)

=============================================================

会话维持:
在Requests中,我们直接使用get()或者post()方法可以模拟网页的请求,但是这实际上是不同的会话session,即相当于用了两个浏览器打开不同的页面,那么会遇到的问题是:第一次用post方法登录了页面,第二次使用get方法请求个人信息页面,但是由于实际上是打开了两个浏览器,所以第二次并不能获取成功(确实可以每次加上同样的cookies)。

其实解决上述办法的主要方式是维持同一个session,即每次打开浏览器的新的选项卡,而不是新浏览器:

import requests
s = requests.Session()  # 这一行是重点,以后每次使用这个session对象
s.get('http://httpbin.org/cookies/set/number/123456789')
r = s.get('http://httpbin.org/cookies')
print(r.text)

=============================================================

SSL证书验证:
在Requests中,我们可以使用verify这个参数来控制是否验证参数,如果不加,默认验证证书。比如我们爬去12306,会提示SSLError的错误,解决方法:

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

然后成功,但是会报出警告,我们尝试忽略这个警告:

from requests.packages import urllib3
urllib3.disable_warnings()

或者我们可以捕获警告到日志:

import logging
logging.captureWarnings(True)

============================================================

超时设置:
我们应当设置超时时间,不然我们会浪费很多时间去访问一个可能无响应的网站:

import requests
r = requests.get('https://www.taobao.com', timeout=1)

=============================================================

身份认证:
有时候访问网站,可能要求我们身份认证(不是那种网站的会员账号之类的登录),解决办法:

import requests
from requests.auth import HTTPBasicAuth
r = requests.get('http://localhost:5000', auth=HTTPBasicAuth('username', 'password'))
# 可以直接传递一个元组,也是上面的简化方法
r = requests.get('http://localhost:5000', auth=('username', 'password'))

============================================================

使用Prepared Request构建一个Request对象:
我的上一篇文章里面说到了Urilib可以将request表示为一个数据结构,这里我们也可以实现,这个数据结构就叫做Prepared Request:

from requests import Request, Session

url = 'http://httpbin.org/post'
data = {
    'name': 'germey'
}
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'
}
s = Session()
req = Request('POST', url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped)
print(r.text)

你可能感兴趣的:(网络爬虫)