爬虫基本库的使用

使用urllib:
  1. request:他是最基本的HTTP请求模块,可以用来模拟发送请求,只需要给库方法传入URL以及额外的参数
  2. error:异常处理模块,如果出现请求错误,我们可以捕获异常,然后进行其他操作保证程序不会意外停止
  3. parse:工具模块,提供了很多URL处理方法,如拆分,解析,合并等
发送请求
  1. urlopen()
    urllib.request模块提供了基本的工造HTTP请求的方法,利用它可以模拟浏览器的一个请求发起过程同时它还有处理授权验证,重定向,浏览Cookies以及其他内容
import urllib.request

response = urllib.request.urlopen("https://python.org")
print(type(response))		

打印响应的类型,它是一个HTTPResponse对象,主要包含了read(),readinto(),getheaders(),等方法,以及msg, version, status, ,reason,debuglevel, closed等属性

调用response.read()方法可以得到返回的网页内容,调用status属性得到返回的状态码

import urllib.request

response = urllib.request.urlopen("https://python.org")
response.read().decode()		# 网页返回的内容
response.status			# 响应状态码
response.getheaders()			# 响应头
response.info()			# 也可以获得头信息

urllib.request.urlopen(url, data=None, [timeout*], capath=None, cadefault=Fase, context=None)
除了第一个参数传递URL之外,还可以传递附加数据data, 超时时间timeout

  • data 参数是可选的,如果要添加该参数,并且如果它是字节流编码格式的内容,即 bytes 类型,则需要通过 bytes ()方法转化,另外,如果传递了这个参数,则它的请求方式就不再是 GET 方式,而是POST请求
from urllib import parse
from urllib.request import urlopen

data = bytes(parse.urlencode({"word": "hello"}), encoding="utf8")
response = urlopen("http://httpbin.org/post", data=data)

这里我们传了一个参word,值是hello,他需要被转成bytes(字节流)类型才能被传输,转换字节流用了bytes()方法,该方法的第一个参数需要字符串类型,用urllib.parse模块里的urlencode()方法将参数字典转化为字符串,第二个参数指定编码格式

  • timeout()参数设置超时时间,单位是秒,如果超过这个时间,没有得到响应,就是抛出异常
  1. Request
    如果在请求中需要加入Headers等信息,就可以用更强大的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参数构造
  • 第四个参数是请求方的host或者IP
from urllib import request, parse

url = "http://httpbin.org/post"
headers = {
	"User-Agent":"Mozilla/5.1 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36",
}
data = {
	"name": "join"
}

data = bytes(parse.urlencode(data), encoding="utf8")
req = request.Request(url, data=data, headers=headers, methods='POST')
res = request.urlopen(req)

print(res.read().decode())

这里通过四个参数构造了一个请求,URL为请求的URL,data用urlencode()和butes()转为字节流,headers添加了请求头,指定了请求方式为POST

高级用法

对于一些更高级的操作(比如Cookies处理,代理设置等),就需要用到Handler工具了,简而言之,他就是各种处理器,有专门处理登陆验证的,有处理Cookies的,还有处理代理的,利用他们,几乎可以可以做到HTTP请求中所有的事情
urllib.request模块里的BaseHandler类,是其他所有Handler的父类,
在这里插入图片描述

代理
from urllib error import URLError
from urllib.request import ProxyHandler, build_opener

proxy_handler = ProxyHandler({
	"http": "http://127.0.0.1:8421",
	"https": "http://xxx.xxx.xx.xxx:1234".
})
opener = build_opener(proxy_handler)
try:
	response = opener.open("http://www.baidu.com")
	print(response.read().decode())
except URLError as e:
	print(e.reason)

搭建代理,使用ProxyHandler,其参数是一个字典,键名是协议类型,键值是代链接,可以添加多代理,然后利用这个Handler和build_opener方法构建出Opener,使用open()发送请求即可

Cookies
import http.cookiejar, 
from urllib import reuqest

cookie = http.cookiejar.CookieJar()
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
response = opener.open("http://www.baidu.com")

首先声明一个CookieJar对象,接下来,利用HTTPCookieProcessor构建一个Handler,最后利用build_opener ()方法构建出Opener,执行open()函数即可

  1. 将Cookie输出到文件
import http.cookiejar
from urllib import request

filename = "cookies.txt
cookie = http.cookiejar.MozillaCookieJar(filename)
# cookie = http.cookiejar.LWPCookieJar(filename)		  # 保存成LWP格式的Cookies文件
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
response = opener.open("http://www.baidu.com")
cookie.save(ignore_discard=True, ignore_expires=True)

在声明对象时换成MozillaCookieJar,是一个Cookie Jar的子类,可以处理Cookies和文件相关的事件,比如读取和保存Cookies,可以将Cookies保存成Mozilla型浏览器的Cookies格式,

  1. 生成Cookies文件后的读取,以LWPCookieJar格式为例
import http.cookiejar
from urllib import request

cookie = http.cookiejar.LWPCookieJar()
cookie.load("cookie.txt", ignore_discard=True, ignore_expires=True)
handler = request.HTTPCookieProcessor(cookie)
opener = request.build_opener(handler)
response = opener.open("http://www.baidu.com")

必须先生成LWPCookieJar对象,再调用load()来读取本地的cookies文件,获取到Cookies内容,之后用同样的方法构建Handler和Opener即可

https://docs.python.org/3/library/urllib.request.html#basehandler-objects
官方文档

处理异常
  1. URLError
    urllib的error模块定义了由request产生的异常,URLError类来自urllib的error模块,他继承自OSError,具有一个reason属性,返回错误的原因
from urllib import request, error

try:
	response = request.urlopen("http://www.baidu.com/xxx.xxx")
except error.URLErrpr as e:
	print(e.reason)

我们打开一个不存在的页面,当我们捕获这个URlError异常时,运行结果为Not Found,这样就可以避免程序因异常而终止

  1. HTTPError
    它是URLError的子类,用来处理HTTP请求错误,比如认证请求失败等,他又三个属性,
  • code: 返回HTTP的状态码,404,500等
  • reason:和父类一样返回错误原因
  • headers:返回请求头
    因为URLError是HTTPError的父类,所以可以先捕获子类的异常,再去捕获父类的异常,最后用else处理正常正常流程的逻辑即可
from urllib import request, error
try:
	response = request.urlopen("http:xxx.com/xxx.html")
except error.HTTPError as e:
	print(e.code, e.reason, e.headers)
exceot error.URLError as e:
	print(e.reason)
else:
	print("Request Success")
解析链接
  1. urlparse()该方法可以实现URL的识别和分段
from urllib import parse

result = parse.urlparse("http://www.baidu.com/index.html;user?id=5#comment")
print(type(resule), result)

# 使用urlparse()对URL进行解析,输出结果
ParseResult(scheme='http', netloc='www.baidu.com', path='/index.html', params='user', query='id=5', fragment='comment')

urlparse()方法拆分为了6部分,解析时有特定的分隔符,://前面的是scheme,代表协议;第一个/前面是netloc,是域名;后面是path,分号;后面是params,代表参数,问号?后面是查询条件query,一般用作GET请求,井号#后面是锚点,用于直接定位页面的下拉位置

  1. urlunparse(),他接受的参数一个长度为6位的可迭代对象,否则会抛出异常
    实现URL的构造
from urllib import parse

data = ['http', 'www.baidu.com', 'index.html', 'user', 'id=5', 'comment']

# 运行结果如下:
http://www.baidu.com/index/html;user?id=5#comment 
  1. urlencode()有时为了方便的构造参数,实现用字典表示,在转化为URL的参数时,只需要使用即可
from urllib import parse

params = {
	"name": "lee",
	"age": 20,
}

base_url = "http://www.baidu.com?"
result = base_url + parse.urlencode(params)

# 运行结果
http://www.baidu.com?name=leey&age=20
  1. quote()当URL中带有中文参数时,有时可能会导致乱码,可以用这个方法将中文字符转换为URL编码:
from urllib import parse

keyword = "壁纸“
result = "http://www.baidu.com?wd=" + parse.quote(keyword)
print(result)

# 先定义一个中文的搜索文字,然后用quote()方法对其进行URL编码,拼接到前面的URL后面
http://www.baidu.com?wd=%E5%A3%81%E7%BA%B8
  1. unquote()对URL进行解码
from urllib import parse

result = parse.unquote(http://www.baidu.com?wd=%E5%A3%81%E7%BA%B8)
print(result)

# 对编码后的内瓤进行还原
http://www.baidu.com?wd=壁纸

requests的使用

  1. GET请求,首先构建一个最简单的GET请求,该网站站会判断如果客户
    端发起的是GET 请求的话,它返回相应的请求信息
import requests

r = request.get("http://httpbin.org/get)
print(r.text)

# 运行结果 ——————————————————————
{
  "args": {}, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.18.4"
  }, 
  "origin": "219.144.212.60", 
  "url": "http://httpbin.org/get"
}

对于GET请求如果想添加一些参数可以使用params参数,添加请求头使用headers参数

import requests
params = {
	"name": "lee",
	"age": 18
}
headers = {
	"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
}

r = requests.get("http://httpbin.org/get", params=params)
print(t.text)

# 运行结果————————————
{
  "args": {
    "age": "18", 
    "name": "lee"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Host": "httpbin.org", 
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36"
  }, 
  "origin": "219.144.212.60", 
  "url": "http://httpbin.org/get?name=lee&age=18"
}

可以看到,链接被自动构造为"http://httpbin.org/get?name=lee&age=18"。并且请求头中的User-Agent也变为了我们设置的headers中的内容。调用json()方法,就可以将返回结果是json格式的字符串转换为字典形式,只对返回的结果是JSON格式才有效,否则会报错

import requests

r = requests.get("http://httpbin.org/get")
print(type(r.json()))
print(r.json())
抓取二进制数据

图片,视频,音频等本质都是由二进制组成的,所以要抓取他们,就要拿到他们的二进制码

import requests

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

# 打印结果的前面有一个b,代表是bytes类型的数据,接着将图片保存成文件,wb以二进制写入的形式打开文件
with open("favicon.ico", "wb") as f:
	f.write(r.content)		# content属性得到二进制的响应内容

程序运行成功后就会看到文件夹下出现了favicon.ico的图标

  1. POST请求
import requests

data = {"name": "lee"}

res = requests.post("http:httpbin.org/post", data=data)
# 运行结果————————
{
  "args": {}, 
  "data": "", 
  "files": {}, 
  "form": {
    "name": "lee"
  }, 
  "headers": {
    "Accept": "*/*", 
    "Accept-Encoding": "gzip, deflate", 
    "Connection": "close", 
    "Content-Length": "8", 
    "Content-Type": "application/x-www-form-urlencoded", 
    "Host": "httpbin.org", 
    "User-Agent": "python-requests/2.18.4"
  }, 
  "json": null, 
  "origin": "117.22.250.169", 
  "url": "http://httpbin.org/post"
}

可以看到POST请求传输的数据在form中,而GET提交的数据在args中

3.响应信息

import requests
res = requests.get("http://www.jianshu.com")
print(res.status_code)			# 响应状态码
print(res.headers)				# 响应头
print(res.request.headers)			# 请求头
print(res.url)				# 请求的URL
print(res.cookies)			# Cookies
requests高级用法

1.文件上传

import reuqests

data = {"file": open("123.jpg", 'rb')}
res = requests.post("http://httpbin.org/post", files=data)
print(res.text)

需要上传的文件必须和脚本在同一目录下才能open,

  1. Cookies
    使用requests获取和设置Cookies。通过cookies属性便可得到Cookies,然后遍历即可得到每个Cookie的键值
import requests

res = requests.get("http://www.baidu.com")
print(res.cookies)

for k, v in res.cookies.items():
	print(k ,v)
  1. Session会话维持
    在requests中,直接用get()或post()等方法模拟网页发送请求是相当于不同的会话,也就是说相当于用两个浏览器打开了不同的页面。解决方法就是维持同一个会话—Session对象,利用它,可以方便的维护一个会话,不用担心Cookies的问题
import requests

requests.get("http://httpbin.org/cookies/set/numner/123")
r = requests.get("http://httpbin.org/cookies")
print(r..text)
# 运行结果——————
{
  "cookies": {}
}

当我们第一步在测试网站设置了Cookies之后,随后又请求网站下的Cookies,这样并不能获取到。再利用Session试试

import requests

s = requests.Session()
res = s.get("http://httpbin.org/cookies/set/number/123")
print(res.text)
res_2 = s.get("http://httpbin.org/cookies")
print(res.text)

# 运行结果
{
  "cookies": {
    "number": "123"
  }
}

运行之后发现两次的运行结果相同,表示成功获取到了Cookies,利用Session,可以模拟同一个会话而不用担心Cookies的问题

  1. SSL证书验证
    requests的verify参数控制是否检查SSL证书,如果不加verify参数,默认是True,会自动验证
res = requests.get("https://www.12306.cn", verify=False)
print(res.status_code)

不过它会报一个警告,建议指定证书,我们可以忽略警告

import requests
from requests.packages import urllib3

urllib3.disable.warnings()			# 忽略警告
res = requests.get("https://12306.cn")
print(res.status_code)
  1. 代理设置,利用proxies参数
proxies = {
		"http": "http://111.111.111.111:port",
		"https": "https://111.111.111.111:port",
}
res = requests.get("http://taobao.com", proxies=proxies)

如果是代理HTTP Basic Auth认证方式,可以使用 http://user:password@host:port 语法来设置

proxies = {
	"http"; "http://user:password@111.111.111.111:port"
}
res = requests.get("http://www.baidu.com", proxies=proxies)
  1. 超时设置
    当网络不好的情况下,我们可能会因为太久得不到响应而报错,为了避免,应该设置一个超时时间,用到timeout参数,这个时间的计算是发出请求到服务器返回响应的时间
res = requests.get("http://www.baidu.com", timeout=1)

通过将超时时间设置为1秒,如果1秒没有响应,那就抛出异常。实际上,请求分为连接(connect)和读取(read)两个阶段,timeout设置的是两者总和,默认timeout为None,即永久等待

  1. 身份验证,在请求网站时,有可能遇到这个认证页面
    在这里插入图片描述

此时可以使用requests自带的身份认证功能

import requests

# 这是一种简便的写法,直接传一个元祖,他会默认使用request.auth.HTTPBasicAuth类来认证
res = requests.get("http://localhost:5000", auth=("username", "password"))

如果用户名和密码正确,请求就会自动验证成功,返回200

  1. Prepared Request
    在urllib中,可以将请求表示为数据结构,其中各个参数都可以通过Request对象来表示。在Requests中,这个数据结构叫Prepared Request
from requests import Request, Session

url = "xxx"
data = {"xxx": "xxxx"}
headers = {"UA": "xxx"}

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

这里我们导入了Request和Session,首先创建一个Session对象,然后用url, data, headers构建一个Request对象,这时需要用Session的prepare_request()方法将其转换为Prepared Request对象,然后用send()方法发送即可,查看运行结果,达到了同样的POST结果

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值