Python网络爬虫学习笔记(二)基本库的使用

基本库的使用

最基础的 HTTP 库有 urllib 、 httplib2 、 requests 、 treq 等 。

使用urlib

urlib 包含四个模块
request : 它是最基本的 HTTP 请求模块,可以用来模拟发送请求 。 就像在浏览器里输入网址,然后回车一样,只需要给库方法传入 URL 以及额外的参数,就可以模拟实现这个过程了 。
error : 异常处理模块,如果出现请求错误 , 我们可以捕获这些异常,然后进行重试或其他操作以保证程序不会意外终止 。
parse : 一个工具模块,提供了许多 URL 处理方法,比如拆分、解析 、 合并等 。
robot parser :主要是用来识别网站的 robots.txt 文件,然后判断哪些网站可以爬,哪些网站不可以爬,它其实用得比较少。

发送请求

urllib 的 request 模块
1. urlopen()
urllib . request 模块提供了最基本的构造 HTTP 请求的方法, 利用它可以模拟浏览器的一个请求发起过程, 同时它还带有处理授权验证( authenticaton )、重定向( redirection) 、浏览器 Cookies 以及其他内容。

例:

import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(response.read().decode('utf-8'))

运行结果:得到网页的源代码
Python网络爬虫学习笔记(二)基本库的使用
利用 type ()方法输出响应的类型:

import urllib.request
response = urllib.request.urlopen('https://www.python.org')
print(type(response))

输出:
Python网络爬虫学习笔记(二)基本库的使用
可以发现,response是一个 HTTPResposne 类型的对象,主要包含 read()、readinto()、getheader(name)、getheaders()、fileno()等方法,以及msg、version、status、reason、debuglevel、closed 等属性。

urlopen( )函数的 API:
urllib.request.urlopen(url, data=None,[timeout,]*,cafile=None, capath=None, cadefault=False, context=None)
• data 参数
如果要添加该参数,则它的请求方式就不再是 GET 方式,而是 POST 方式 。并且如果它是字节流编码格式的内容,即 bytes 类型,则需要通过 bytes()方法转化。

import urllib.parse
import urllib.request
data = bytes(urllib.parse.urlencode({'word':'hello'}), encoding = 'utf-8')
response = urllib.request.urlopen('http://httpbin.org/post', data=data)
print(response.read())

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
传递的参数州现在了 form 字段中,这表明是模拟了表单提交的方式,以 POST 方式传输数据。

• timeout 参数
timeout 参数用于设置超时时间,单位为秒,意思就是如果请求超 出了设置的这个时间, 还没有得到响应,就会抛出异常。如果不指定该参数 ,就会使用全局默认时间 。 它支持 HTTP , HTTPS 、FTP请求 。
例:

import urllib.request
response = urllib.request.urlopen('http://httpbin.org/get', timeout=l)
print(response.read())

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
可以通过设置这个超时时间来控制一个网页如果长时间未响应,就跳过它的抓取 。 这可以利用 try except 语句来实现 ,相关代码如下:

import socket
import urllib.request
import urllib.error
try:
    response = urllib.request.urlopen('http://httpbin.org/get', timeout=0.1)
except urllib.error.URLError as e:
	if isinstance(e.reason,socket.timeout):
	    print('TIME OUT')

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
捕获了 URLError 异常,判断异常是 socket.timeout 类型(意思就是超时异常)

· 其他参数
context 参数:它必须是 ssl.SSLContext 类型,用来指定SSL 设置
cafile 和 capath 这两个参数分别指定 CA 证书和它的路径,这个在请求 HTTPS 链接时会有用
cadefault 参数现在已经弃用了,其默认值为 False

urlopen( )方法的用法可以参见官方文档 : https://docs.python.org/3/library/urllib.request.html#module-urllib.request

2. Request
利用 urlopen ()方法可以实现最基本请求的发起,但这几个简单的参数并不足以构建一个完整的请求 。 如果请求中需要加入Headers 等信息,就可以利用更强大的 Request 类来构建。
例:Request 的用法

import urllib.request
request = urllib.request.Request('https://python.org')
response = urllib.request.urlopen(request)
print(response.read().decode('utf-8'))

依然是用 urlopen( )方法来发送这个请求,只不过这次该方法的参数不再是 URL,而是一个 Request 类型的对象。 通过构造这个数据结构,一方面可以将请求独立成一个对象,另一方面可更加丰富和灵活地配置参数。

Request的构造方法
class urllib.request.Request(url,data=None, headers={ }, origin_req_host=None, unverifiable=False, method=None)
第一个参数url 用于请求 URL ,这是必传参数,其他都是可选参数。
第二个参数 data 如果要传,必须传 bytes (字节流)类型的 。 如果它是字典,可以先用urllib.parse 模块里的 urlencode()编码 。
第三个参数 headers 是一个字典,它就是请求头,我们可以在构造请求时通过 headers 参数直接构造,也可以通过调用请求实例的 add_header( )方法添加。
添加请求头最常用的用法就是通过修改 User-Agent 来伪装浏览器,默认的 User-Agent 是Python-urllib,我们可以通过修改它来伪装浏览器 。 比如要伪装火狐浏览器,你可以把它设置为 :
Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0
第四个参数 origin_req_host 指的是请求方的 host 名称或者 IP 地址。
第五个参数 unverifiable 表示这个请求是否是无法验证的,默认是 False ,意思就是说用户没有足够权限来选择接收这个请求的结果。 例如,我们请求一个 HTML 文档中的图片,但是我们没有自动抓取图像的权限,这时 unverifiable 的值就是 True 。
第六个参数 method 是一个字符串 ,用来指示请求使用的方法,比如 GET、POST和PUT等 。
例:

from urllib import request,parse
url = 'http://httpbin.org/post'
headers = {
	'User-Agent':' Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0',
	'Host':'httpbin.org'
}
dict = {
	'name':'Germey'
}
data= bytes(parse.urlencode(dict), encoding='utf8')
req = request.Request(url=url, data=data, headers=headers, method='POST')
response = request.urlopen(req)
print(response.read().decode('utf-8'))

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
headers 也可以用 add_header( )方法来添加:

req = request.Request(url=url, data=data, method='POST')
req .add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:81.0) Gecko/20100101 Firefox/81.0')

3. 高级用法
对于一些更高级的操作(比如 Cookies 处理 、 代理设置等),就需要更强大的工具 Handler。可以把它理解为各种处理器,有专门处理登录验证的,有处理 Cookies 的,有处理代理设置的 。 利用它们,我们几乎可以做到 HTTP请求中所有的事情。

urllib.request 模块里的 BaseHandler 类:所有其他 Handler 的父类,提供了最基本的方法,例如 default_open( )、protocol_request ( )等。
各种 Handler 子类举例:
HTTPDefaultErrorHandler :用于处理 HTTP 响应错误,错误都会抛出 HTTP Error 类型的异常 。
HTTPRedirectHandler :用于处理重定向 。
HTTPCookieProcessor : 用于处理 Cookies 。
ProxyHandler :用于设置代理 , 默认代理为空 。
HTTPPasswordMgr :用于管理密码,它维护了用户名和密码的表。
HTTPBasicAuthHandler : 用于管理认证,如果一个链接打开时需要认证,那么可以用它来解决认证问题。
有其他的 Handler 类可以参考官方文档: https://docs.python.org/3/library/urllib.request.html#urllib.request.BaseHandler。

另一个比较重要的类是 OpenerDirector
可以称为Opener
urlopen( )这个方法,就是urllib 为我们提供的一个 Opener。
之前使用的 Request 和 urlopen( )相当于类库为你封装好的常用的请求方法,利用它们可以完成基本的请求,实现更高级的功能,就需要深入一层进行配置,使用更底层的实例来完成操作。
一般我们利用 Handler 来构建 Opener。

用法示例:
·验证(有些网站打开时弹出提示框,直接提示输入用户名和密码)
请求这样的页面时,可借助 HTTPBasicAuthHandler

from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler, build_opener
from urllib.error import URLError
username = username
password ='password'
url = 'http://localhost:sooo/'
p = HTTPPasswordMgrWithDefaultRealm() 
p.add_password(None, url, username,password)##利用 add_password()添加进去用户名和密码
auth_handler = HTTPBasicAuthHandler(p)##实例化 HTTPBasicAuthHandler 对象,其参数是HTTPPasswordMgrWithDefaultRealm 对象
opener = build_opener(auth_handler)##利用这个 Handler 并使用 build_opener()方法构建一个 Opener
try:
	result = opener.open(url)##利用 Opener 的 open()方法打开链接,就可以完成验证了 
	html = result.read().decode('utf 8')
	print(html)
except URLError as e:
	print(e.reason)

·代理

from urllib.error import URLError
from urllib.request import ProxyHandler, build_opener
proxy_handler = ProxyHandler({
'http':'http://127.0.0.1:9743',
'https':'https://127.0.0.1:9743'
})
opener = build_opener(proxy_handler)
try:
	response = opener.open('https://www.baidu.com')
	print(response.read().decode('utf-8'))
except URLError as e:
	print(e.reason)

这里在本地搭建了一个代理,它运行在 9743 端口上 。
使用了 ProxyHandler,其参数是一个字典,键名是协议类型(比如 HTTP 或者 HTTPS 等),键值是代理链接,可以添加多个代理。然后,利用这个 Handler 及 build_opener()方法构造一个 Opener,之后发送请求即可 。

• Cookies
例子:将网站的 Cookies 获取下来

import http.cookiejar, urllib.request
cookie = http.cookiejar.CookieJar()
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
for item in cookie:
	print(item.name+"="+item.value)

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
Cookies 实际上是以文本形式保存,可以输出成文件格式。

import http.cookiejar, urllib.request
filename = 'cookies.txt'
cookie = http.cookiejar.MozillaCookieJar(filename)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response = opener.open('http://www.baidu.com')
cookie.save(ignore_discard=True, ignore_expires=True)

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
调用 load ()方法可以读取本地的 Cookies 文件,获取到了 Cookies 的内容,前提是我们首先生成了 LWPCookieJar 格式的 Cookies ,并保存成文件,然后读取 Cookies 之后使用同样的方法构建 Handler 和l Opener 即可完成操作。

cookie = http.cookiejar.LWPCookieJar()
cookie.load('cookies.txt', ignore discard=True, ignore_expires=True)
handler = urllib.request.HTTPCookieProcessor(cookie)
opener = urllib.request.build_opener(handler)
response= opener.open('http://www.baidu.com')
print (response.read().decode('utf-8'))

实现更多的功能,可以参考官方文档的说明:https://docs.python.org/3/library/urllib.request.html#basehandler-objects

处理异常

urllib 的 error 模块定义了由 request 模块产生的异常,如果出现了问题,request 模块便会抛出error 模块中定义的异常。
1.URLError
URLError 类来自 urllib 库的 error 模块,它继承自 OSError 类,是 error 异常模块的基类,由 request模块生的异常都可以通过捕获这个类来处理。具有一个属性 reason ,返回错误的原因 。
例:

from urllib import request,error
try:
	response = request.urlopen ('https://cuiqingcai.com/index.htm')
except error.URLError as e:
	print(e.reason)

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
2. HTTPError
它是 URLError 的子类,专门用来处理 HTTP 请求错误,比如认证请求失败等 ,它有如下 3 个属性。
口 code : 返回 HTTP 状态码,比如 404 表示网页不存在, 500 表示服务器内部错误等 。
口 reason :同父类一样,用于返回错误的原因 。
口 headers : 返回请求头 。

例子:

from urllib import request,error
try:
	response = request.urlopen ('https://cuiqingcai.com/index.htm')
except error.HTTPError as e:
	print(e.reason, e.code, e.headers, sep='\n ')

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
因为 URLError 是 HTTPError 的父类,所以可以先选择捕获子类的错误,再去捕获父类的错误,更好的写法如下:

from urllib import request,error
try:
	response = request.urlopen ('https://cuiqingcai.com/index.htm')
except error.HTTPError as e:
	print(e.reason, e.code, e.headers, sep='\n ')
except error.URLError as e:
	print(e.reason)
else:
	print("Request Successfully")

这样就可以做到先捕获 HTTPError,如果不是HTTPError 异常,就会捕获 URLError 异常,输出错误原因 。

有时候, reason 属性返回的不一定是字符串,也可能是一个对象 。 实例:

import socket
import urllib.request
import urllib.error
try:
	response = urllib.request.urlopen('https://www.baidu.com', timeout = 0.01)
except urllib.error.URLError as e:
	print(type(e.reason))
	if isinstance(e.reason, socket.timeout):
		print('TIME OUT')

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
附加
isinstance(object, classinfo)函数来判断一个对象是否是一个已知的类型,类似 type()。
object = 实例对象。
classinfo = 可以是直接或间接类名、基本类型或者由它们组成的元组。
type() 不会认为子类是一种父类类型,不考虑继承关系。
isinstance() 会认为子类是一种父类类型,考虑继承关系。
如果要判断两个类型是否相同推荐使用 isinstance()。

解析链接

urllib 库里提供了 parse 模块,它定义了处理 URL 的标准接口,例如实现 URL 各部分的抽取、合并以及链接转换。 它支持如下协议的 URL 处理:file、ftp、gopher、hdl、http、https、imap、mailto、mms、news、nntp、prospero、rsync、rtsp、rtspu、sftp、sip、sips、snews、svn、svn+ssh、telnet和wais。
1. urlparse()
该方法可以实现 URL 的识别和分段
例:

from urllib.parse import urlparse

result = urlparse('http://www.baidu.com/index.html;user?id=S#comment')
print(type(result), result,sep = '\n')

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
返回结果是一个 ParseResult 类型的对象,它包含 6 个部分,分别是 scheme(协议)、netloc(域名)、path(访问路径)、params(参数)、query(查询条件)和 fragment(锚点,用于直接定位页面内部的下拉位置)。
urlparse的API:
urllib.parse.urlparse(urlstring, scheme=”, allow_fragments=True)
口 urlstring :这是必填项,即待解析的 URL 。
口 scheme :它是默认的协议(比如 http 或 https 等)。scheme 参数只有在 URL 中不包含 scheme 信息时才生效 。如果 URL中有 scheme 信息,就会返回解析出的 scheme 。
口 allow_fragments :即是否忽略 fragment 。 如果它被设置为 False ,fragment 部分就会被忽略,它会被解析为 path 、 parameters 或者 query 的一部分,而 fragment 部分为空 。

2. urlunparse()
urlparse( )的对立方法 urlunparse() 。 它接受的参数是一个可迭代对象,但是它的长度必须是 6 , 否则会抛出参数数量不足或者过多的问题。
例:

from urllib.parse import urlunparse
data =['http', 'www.baidu.com','index.html', 'user','a=6',' comment']
print(urlunparse(data))

运行结果:实现了 URL 的构造。
Python网络爬虫学习笔记(二)基本库的使用

3. urlsplit()
这个方法和 urlparse( )方法非常相似,只不过它不再单独解析 params(参数) 这一部分,只返回 5 个结果 ,params 会合并到 path 中 。

from urllib.parse import urlsplit

result = urlsplit('http://www.baidu.com/index.html;user?id=S#comment')
print(type(result), result,sep = '\n')

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
返回结果是 SplitResult,它其实也是一个元组类型 ,既可以用属性获取值,也可以用索引来获取。
例子:

from urllib.parse import urlsplit
result = urlsplit('http://www.baidu.com/index.html;user?id=S#comment')
print(result.scheme, result[0])

运行结果:
Python网络爬虫学习笔记(二)基本库的使用

4. urlunsplit()
与 urlunparse ()类似,它也是将链接各个部分组合成完整链接的方法,传人的参数也是一个可迭代对象,例如列表 、 元组等,唯一的区别是长度必须为 5 。

from urllib.parse import urlunsplit
data = ['http','www.baidu.com','index.html','a=6','comment']
print(urlunsplit(data))

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
5. urljoin()
生成链接还有另一个方法,就是 urljoin( )方法,可以提供一个 base_url (基础链接 )作为第一个参数,将新的链接作为第二个参数,该方法会分析 base_url 的 scheme 、netloc 和 path这3 个内容并对新链接缺失的部分进行补充,最后返回结果。而 base_url 中的 pa rams 、 query 和 fragment是不起作用的 。
例:

from urllib.parse import urljoin
print(urljoin('http://www.baidu.com','FAQ.html'))
print(urljoin('http://www.baidu.com','https://cuiqingcai.com/FAQ.html'))
print(urljoin('http://www.baidu.com/about.html','https://cuiqingcai.com/FAQ.html'))
print(urljoin('http://www.baidu.com/about.html','https://cuiqingcai.com/FAQ.html?question=2'))
print(urljoin('http://www.baidu.com?wd=abc','https://cuiqingcai.com/index.php'))
print(urljoin('http://www.baidu.com','?category=2#comment'))
print(urljoin('www.baidu.com','?category=2#comment'))
print(urljoin('www.baidu.com#comment','?category=2'))

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
6. urlencode()
例子:

from urllib.parse import urlencode
params = {
	'name': 'germey',
	'age ': 22
}
base_url = 'http://wwwbaiducom?'
url = base_url + urlencode(params)
print(url)

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
7. parse_qs()
一串 GET 请求参数,利用 parse_qs ()方法, 就可以将它转回字典
例子:

from urllib.parse import parse_qs
query = 'name=germey&age=22'
print(parse_qs(query))

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
8. parse_qsl()
parse_qsl()方法,用于将参数转化为元组组成的列表
Python网络爬虫学习笔记(二)基本库的使用
运行结果是一个列表,而列表中的每一个元素都是一个元组,元组的第一个内容是参数名,第二个内容是参数值。
9. quote()
该方法可以将内容转化为 URL 编码的格式。URL 中带有中文参数时,有时可能会导致乱码的问题,用这个方法可以将中文字符转化为 URL 编码。
例子:

from urllib.parse import quote
keyword ='壁纸'
url ='https://www.baidu.com/s?wd='+ quote(keyword)
print(url)

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
10. unquote()
进行 URL 解码
例:

from urllib.parse import unquote

url ='https://www.baidu.com/s?wd=%E5%A3%81%E7%BA%B8'
print(unquote(url))

运行结果:
Python网络爬虫学习笔记(二)基本库的使用

分析 Robots 协议

利用 urllib 的 robot parser 模块,我们可以实现网站 Robots 协议的分析。
1. Robots 协议
Robots 协议也称作爬虫协议、机器人协议,它的全名叫作网络爬虫排除标准( Robots Exclusion Protocol ),用来告诉爬虫和搜索引擎哪些页面可以抓取,哪些不可以抓取。 它通常是一个叫作 robots.txt的文本文件,一般放在网站的根目录下 。
当搜索’爬虫访问一个站点时,它首先会检查这个站点根目录下是否存在 robots.txt 文件,如果存在,搜索爬虫会根据其中定义的爬取范围来爬取。 如果没有找到这个文件,搜索爬虫便会访问所有可直接访问的页面。

样例:将内容保存成 robots.txt 文件,放在站的根目录下,和网站的人口文件(比如 index.php 、 index.html 和 index.jsp 等)放在一起。

##实现了对所有搜索爬虫只允许爬取 public 目录的功能
User-agent: *       /*描述爬虫的名称,如果有多条 User-agent 记录,则就会有多个爬虫会受到爬取限制,但至少需要指定一条。*/
Disallow: /         /* 指定了不允许抓取的目录,置为/则代表不允许抓取所有页面 */
Allow: /public/     /*Allow 一般和 Disallow 一起使用,一般不会单独使用,用来排除某些限制 。 设置为/public/,则表示所有页面不允许抓取,但可以抓取 public 目录。*/
##禁止所有爬虫访问任何目录的
User-agent: *
Disallow: /
## 允许所有爬虫访问任何目录
User-agent: *
Disallow: 
##禁止所有爬虫访问网站某些目录的
User-agent: *
Disallow: /private/
Disallow: /tmp/
##只允许某一个爬虫访问
User-agent: WebCrawler
Disallow: 
User-agent: *
Disallow: /

2. 爬虫名称
Python网络爬虫学习笔记(二)基本库的使用
3. robotparser
该模块提供了一个类 RobotFileParser ,它可以根据某网站的robots.txt 文件来判断一个爬取爬虫是否有权限来爬取这个网页。
该类用起来非常简单,只需要在构造方法里传人 robots.txt 的链接即可。
类声明:
urllib.robotparser.RobotFileParser(url=’ ’)
也可以在声明时不传人,默认为空,最后再使用 set_url()方法设置

这个类常用的几个方法:
口 set_url( ): 用来设置 robots. txt 文件的链接 。 如果在创建 RobotFileParser 对象时传入了链接,那么就不需要再使用这个方法设置了 。
口 read( ): 读取 robots.txt 文件并进行分析 。 注意,这个方法执行一个读取和分析操作,如果不调用这个方法 ,接下来的判断都会为 False 。 这个方法不会返回任何内容,但是执行了读取操作 。
口 parse( ): 用来解析 robots.txt 文件,传人的参数是 robots.txt某些行的内容 ,它会按照 robots.txt的语法规则来分析这些内容。
口 can_fetch( ): 该方法传人两个参数 ,第一个是 User-agent,第二个是要抓取的URL。返回的内容是该搜索引擎是否可以抓取这个 URL ,返回结果是 True 或 False a
口 mtime (): 返回的是上次抓取和分析 robots.txt 的时间,这对于长时间分析和抓取的搜索爬虫是很有必要的,你可能需要定期检查来抓取最新的 robots.txt。
口 modified () :它同样对长时间分析和抓取的搜索爬虫很有帮助,将当前时间设置为上次抓取和分析 robots.txt 的时间 。

实例:

from urllib.robotparser import RobotFileParser
rp = RobotFileParser() ##首先创建 RobotFileParser对象
rp.set_url('http://www.jianshu.com/robots.txt')##通过set_url()方法设置了 robots.txt 的链接
rp.read()
print(rp.can_fetch('*','http://www.jianshu.com/p/b67554025d7d'))##利用 can_fetch ()方法判断了网页是否可以被抓取
print(rp.can_fetch('*','https://www.jianshu.com/search?q=python&page=1&type=note'))

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
不用 set_url( )方法的话,可以在声明时直接用如下方法设置 :
rp = RobotFileParser(‘http://www.jianshu.com/robots.txt’)
同样可以使用 parse ( )方法执行读取和分析:
rp.parse(urlopen(‘http://www.jianshu.com/robots.txt’).read().decode(’ utf-8’).split(’\n’))

使用 requests

基本用法

urllib 库中的 urlopen( )方法实际上是以 GET 方式请求网页,而 requests 中相应的方法就是 get( )方法,得到一个 Response 对象。
分别用 post( )、 put( )、 delete( )等方法可以实现了 POST、PUT、DELETE 等请求。

1.GET 请求
·基本实例

text( )方法得到的是str数据类型。
content( )方法得到的是Bytes类型。
json( )方法得到的是json数据。
·抓取二进制数据
以 GitHub 的站点图标为例:

import requests
headers = {
"user-agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.1.3228.1 Safari/537.36"
}
r = requests.get("https://github.com/favicon.ico",headers = headers)
print(r.text)
print(r.content)
with open('favicon.ico','wb') as f:
    f.write(r.content)

运行结果:
Python网络爬虫学习笔记(二)基本库的使用Python网络爬虫学习笔记(二)基本库的使用
由于图片是二进制数据,所以前者在打印时转化为 str 类型,会出现乱码 。
用了 open( )方法,它的第一个参数是文件名称,第二个参数代表以二进制写的形式打开,可以向文件里写入二进制数据 。同样地,音频和视频文件也可以用这种方法获取。

2.POST 请求
例子:

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

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
其中 form 部分就是提交的数据

3.响应
text( )方法和 content( )方法获取了响应的内容。 此外,还有很多属性和方法可以用来获取其他信息,比如状态码、响应头、Cookies 等。
例子:分别打印输出 status code 及状态码,headers 属性及响应头,cookies属性及Cookies , url 属性及 URL ,history 属性及请求历史

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)
print(type(r.url), r.url)
print(type(r.history), r.history)

运行结果:
Python网络爬虫学习笔记(二)基本库的使用

requests 还提供了一个内置的状态码查询对象 requests.codes,可以通过比较返回码和内置的成功地返回码来保证请求得到了正常响应。
例子:

import requests
headers = {
'User-Agent':'www.Mozilla/5 .0 (Macintosh; Intel Mac 05 X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36'
}
r = requests.get("http://www.jianshu.com",headers = headers)
exit() if not r.status_code == requests.codes.ok else print("Request Successfully") 

Python网络爬虫学习笔记(二)基本库的使用
Python网络爬虫学习笔记(二)基本库的使用

高级用法

1 . 文件上传
例子:

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

上传的文件favicon.ico 需要和当前脚本在同一目录下
运行结果:包含 files 这个字段Python网络爬虫学习笔记(二)基本库的使用
2. Cookies
urllib 处理过 Cookies ,写法比较复杂,而requests ,获取和设置 Cookies 只需一步即可完成。

import requests
#获取Cookies,调用cookies 属性即可成功得到 Cookies,它是 RequestCookieJar 类型
r = requests.get("https://www.baidu.com")
print(r.cookies)
for key,value in r.cookies.items():#用 items( )方法将其转化为元组组成的列表
    print(key + '='+ value )

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
可以直接用 Cookie 来维持登录状态,微博例子:

import requests
headers = {
'cookie':'SINAGLOBAL=5776359269000.764.1512716468067; login_sid_t=75f0789159a43c4f7d1697171241c4ec; wb_view_log=1920*10801; _s_tentry=-; Apache=5473669888703.581.1607737497444; ULV=1607737497460:6:3:1:5473669888703.581.1607737497444:1606975319122; WBtopGlobal_register_version=2020121209; SCF=AoEZy3eKw8w9JfQwyVlZ2kI79HmpQPqR8zVG_Db2UhquDtqXPCkO0zWMrzNvAcs9iZkEdM-zN9Tv3q9Qe6Mr4cY.; wb_view_log_5863072281=1920*10801; webim_unReadCount=%7B%22time%22%3A1607739041108%2C%22dm_pub_total%22%3A0%2C%22chat_group_client%22%3A0%2C%22chat_group_notice%22%3A0%2C%22allcountNum%22%3A0%2C%22msgbox%22%3A0%7D; SUB=_2AkMoiKmIdcPxrAZZnvsVy2ngZIxH-jybXcB-An7uJhMyAxhu7kseqSVutBF-XIPJPRu_0kTk613PLPL_3Au9toIE; SUBP=0033WrSXqPxfM72wWs9jqgMF55529P9D9WWsYWayimAjHaRCCBg-CjBx; WBStorage=8daec78e6a891122|undefined; UOR=www.madio.net,widget.weibo.com,login.sina.com.cn; cross_origin_proto=SSL',
'user-agent':'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 UBrowser/6.2.4098.3 Safari/537.36'
}
r = requests.get("https://weibo.com/?category=1760",headers = headers)
r.encoding ='utf-8'
print(r.text)

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
也可以通过 cookies 参数来设置,不过需要构造RequestsCookieJar对象,而且需要分割一下 cookies 。
cookies = ‘黏贴cookies在这儿’
for cookie in cookies.split(’,’):
key,value = cookie.split(’=’, 1)
jar.set(key,value)
r = requests.get(“https://weibo.com/?category=1760”,cookies=jar, headers =headers)
首先新建了一个 RequestCookieJar 对象,然后将复制下来的 cookies 利用 split( )方法分割,接着利用 set( )方法设置好每个 Cookie 的 key 和 value,然后通过调用 requests 的 get( )方法并传递给 cookies 参数即可 。

3 会话维持
在 requests 中,如果直接利用 get( )或 post( )等方法可以做到模拟网页的请求,但是这实际上是相当于不同的会话,也就是说相当于用了两个浏览器打开了不同的页面,是两个完全不相关的会话,无法成功获取个人信息。
解决这个问题的主要方法就是维持同一个会话 , 也就是相当于打开一个新的浏览器选项卡而不是新开一个浏览器 。利用Session 对象 ,可以不用每次都设置 cookies。
例子:

import requests
mycookie = {
    'JSESSIONID':'8542C60F57B6A189DAF10319A8F63986'
}
s = requests.Session()
s.get('http://opac.lnu.edu.cn/opac_two/reader/infoList.jsp#',cookies = mycookie)
r = s.get('http://opac.lnu.edu.cn/opac_two/newbook/queryIn.jsp#/cookies')
r.encoding = 'gb2312'
print(r.cookies)

运行结果:
Python网络爬虫学习笔记(二)基本库的使用
4. SSL 证书验证
requests 还提供了证书验证的功能 。 当发送 HTTP 请求的时候,它会检查 SSL 证书,我们可以使用 verify 参数控制是否检查此证书 。 其实如果不加 verify 参数的话,默认是 True ,会自动验证。
当print(response.status_code)出现以下结果则你访问的网站没有被官方CA机构信任:
requests.exceptions.SSLError: (” bad handshake: Error( ((’SSL routines’,’ tls_process_server_certificate’,’ certificate verify failed ’)],)”,)

想避免这个错误,把 verify 参数设置为False 即可 。

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

通过设置忽略警告的方式可屏蔽警告(建议给它指定证书):

from requests.packages import urllib3
urllib3.disable_warnings()

或者通过捕获警告到日志的方式忽略警告 :

import logging
logging.captureWarnings(True)

也可以指定一个本地证书用作客户端证书,这可以是单个文件(包含密钥和证书)或一个包含两个文件路径的元组:

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

5 . 代理设置
对于某些网站,在测试的时候请求几次,能正常获取内容。 但是一旦开始大规模爬取,对于大规模且频繁的请求,网站可能会弹出验证码,或者跳转到登录认证页面 , 更甚者可能会直接封禁客户端的IP,导致一定时间段内无法访问 。
为了防止这种情况发生,需要设置代理来解决这个问题,需要用到 proxies 参数。
可以这样设置 :
requests 还支持 SOCKS 协议的代理。
需要安装 socks 这个库 :
pip3 install ’ requests[socks]’

import requests
proxies = {
"http":"http://user:password@10.10.1.10:3128/"
}
requests.get("https://www.taobao.com", proxies=proxies)  #若代理需要使用 HTTP Basic Auth ,可以使用类似 http://user:password@host:port 这样的语法来设置代理

#SOCKS 协议代理
proxies = {
'http':'sockss://user:password@host:port',
'https':'sockss://user:password@host:port'
}
requests.get("https://www.taobao.com", proxies=proxies)  

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

#请求分为两个阶段,即连接( connect )和读取( read )
#下面设置的 timeout 将用作连接和读取这二者的 timeout 总和 
r = requests.get("https: //www.taobao.com",timeout = 1)

#分别指定,就可以传入一个元组
r = requests.get('https://www.taobao.com', timeout=(5,11, 30))

#timeout 默认是 None ,永久等待

7. 身份认证
在访问网站时,可能会遇到这样的认证页面:
Python网络爬虫学习笔记(二)基本库的使用
可以使用 requests 自带的身份认证功能:

import requests
from requests .auth import HTTPBasicAuth
r = requests.get('http://localhost:5ooo',auth=HTTPBasicAuth(’username',’ password'))
print (r.statu s_code)
#更简单的写法 ,可以直接传一个元组,它会默认使用 HTTPBasicAuth 这个类来认证
r = requests.get('http://localhost: 5ooo ',auth =('username','password'))
#requests 还提供了其他认证方式,如 OAuth 认证 , 不过此时需要安装 oauth 包
#安装命令:pip3 install requests_oauthlib
auth = OAuth1 ('YOUR_APP_KEY',' YOUR_APP_SECRET',
'USER_OAUTH_TOKEN',' USER_OAUTH_TOKEN_SECRET')
requests.get(url, auth=auth)

requests_oauthlib 的官方文档 https://requests-oauthlib.readthedocs.org/

8. Prepared Request
urllib 中可以将请求表示为数据结构,其中各个参数都可以通过一个 Request 对象来表示。在 requests 里同样可以做到,这个数据结构叫 Prepared Request。

from requests import Request, Session
url = 'http://httpbin.org/post '
data = {
'name':'germey'
}
headers = {
'User-Agent' : 'Mozilla/5.o (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/53 .0.2785.116 Safari/537 .36'
}
#引入Request,用url、data和headers参数构造Request对象,调用Session的prepare_request()方法转换为Prepares Request对象
s = Session()
req = Request('POST', url, data=data, headers=headers)
prepped = s.prepare_request(req)
r = s.send(prepped) #调用send()方法发送
print(r.text)

更多的用法可以参考 requests 的官方文梢 : http://docs.python-requests.org/

上一篇:Python3下urllib.parse.urlencode()编码


下一篇:python获取代理需要账户和密码代码模板