1. urllib使用
1.1 一个简单的例子
入门例子html源码
解析百度的
import urllib.request
file = urllib.request.urlopen("http://www.baidu.com")
#data = file.read()
#dataline = file.readline()
datalines = file.readlines()
#print(data)
#print(dataline)
print(datalines)
- read、readline和readlines会设置当前文件指针或者刷新流,直接一起用会有问题。比如先用read再用readlines就会得到空的列表
- urllib文档地址
urllib.request.urlopen
(url, data=None, [timeout, ]*, cafile=None, capath=None, cadefault=False, context=None)函数文档
1.2 保存在文件中并查看部分信息
# -*- coding: utf-8 -*-
from urllib import request
urladd = "http://www.baidu.com"
file = request.urlopen(urladd)
data = file.read()
print(data)
htmlfile = open("baidu.html",'wb')
htmlfile.write(data)
htmlfile.close()
#直接写入html文件
htmlfile2 = request.urlretrieve(urladd,"baidu2.html") #retrieve 是取回的意思
request.urlcleanup()
print(file.info()) #
print(file.getcode()) #状态码
print(file.geturl())
## 1.3 对中文字符的处理
request 下面有一个quote函数,用来对中文等特殊字符进行编码
用法是:
urllib.parse.quote
(string, safe=’/’, encoding=None, errors=None)文档地址
# -*- coding: utf-8 -*-
from urllib import request
urladd = u"https://www.baidu.com/s?ie=UTF-8&wd=urllib 手册"
urladd = request.quote(urladd,safe='/:=?') #不加这句会报错
file = request.urlopen(urladd)
data = file.read()
print(data)
1.4 User-Agent 和 模拟Header
在本机的浏览器按f12,在network下点击第一个url,在最下面有一行RequestHeader:
本机在本系统本网络环境中的user-agent
user-agent:
Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36
User Agent中文名为用户代理,简称 UA,它是一个特殊字符串头,使得服务器能够识别客户使用的操作系统及版本、CPU 类型、浏览器及版本、浏览器渲染引擎、浏览器语言、浏览器插件等。
–from 百度百科
在某些网页设置了反爬虫的机制,没有user-agent的信息会返回403错误,当然有的时候也可以用来伪造user-agnet,header信息除了user-agnet之外还有其他的信息,比如Referer等
两种方法
使用build_opener:
# -*- coding: utf-8 -*- from urllib import request urladd = u"https://www.baidu.com/" header = ("user-agent","Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36") #添加header信息 opener = request.build_opener() opener.addheaders = [header] file = opener.open(urladd) #file = request.urlopen(urladd) data = file.read() print(data)
使用Request:
# -*- coding: utf-8 -*- from urllib import request urladd = u"https://www.baidu.com/" key = "user-agent" value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36" req = request.Request(urladd) req.add_header(key,value) print(req) file = request.urlopen(req) #file = request.urlopen(urladd) data = file.read() print(data)
其实在request.urlopen()的参数中传入字符串会自动生成Request对象
1.5 超时设置
就是request.urlopen()中的timeout参数,单位为秒
# -*- coding: utf-8 -*-
from urllib import request
urladd = u"https://www.baidu.com/"
key = "user-agent"
value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
for i in range(1,10):
try:
req = request.Request(urladd)
req.add_header(key,value)
print(req)
file = request.urlopen(req,timeout=0.5)
#file = request.urlopen(urladd)
data = file.read()
print(data)
except Exception as e:
print(str(e))
1.6 HTTP请求
1.6.1 使用get请求访问百度并搜索一个关键词
# -*- coding: utf-8 -*-
from urllib import request
urladd = "https://www.baidu.com/s?&wd=" + request.quote("我的老家") #此处需要编码
key = "user-agent"
value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
req = request.Request(urladd) #构造url请求对象
req.add_header(key,value) #加入头
file = request.urlopen(req,timeout=1) #设置时间
#file = request.urlopen(urladd)
data = file.read()
print(data)
file = open("baidu_wd.html",'wb')
file.write(data)
file.close()
- url地址请求的格式是”http://网址?字段名1=字段内容1&字段名2=字段内容2”
1.6.2 POST提交表单
要使用parse模块,parse模块是用来解析的
# -*- coding: utf-8 -*-
from urllib import request
from urllib import parse
urladd = "http://www.iqianyue.com/mypost/"
key = "user-agent"
value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
postdata = parse.urlencode({
"name":"ceo@iqianyue.com",
"pass":"aA123456"
}).encode('utf-8') #这里一定要调用encode方法来编码
req = request.Request(urladd,data=postdata)
req.add_header(key,value)
#req.data = postdata #可以用这个来指定成员
file = request.urlopen(req,timeout=10)
#file = request.urlopen(urladd)
data = file.read()
print(data)
file = open("post.html",'wb')
file.write(data)
file.close()
- 传递的表单就是在html代码的form条目下,每项的名称就是name=后面的字段,每项的有值,需要用字典包起来。再编码,这是Request对象的一部分
1.6.3 代理服务器设置
# -*- coding: utf-8 -*-
from urllib import request
from urllib import parse
def use_proxy(proxy_addr,urladdr):
proxy = request.ProxyHandler({'http':proxy_addr}) #设置代理的IP和端口
opener = request.build_opener(proxy,request.HTTPHandler)
request.install_opener(opener) #安装全局的opener对象
key = "user-agent"
value = "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/61.0.3163.79 Safari/537.36"
postdata = parse.urlencode({
"name": "ceo@iqianyue.com",
"pass": "aA1234567"
}).encode('utf-8')
req = request.Request(urladd, data=postdata)
req.add_header(key, value)
# req.data = postdata
file = request.urlopen(req, timeout=10)
# file = request.urlopen(urladd)
data = file.read()
return data
urladd = "http://www.iqianyue.com/mypost/"
proxy_addr = "118.114.77.47:8080"
data = use_proxy(proxy_addr=proxy_addr,urladdr=urladd)
file = open("post_proxy.html",'wb')
file.write(data)
file.close()
- 安装全局的opener需要传入句柄handler对象,上面的代码中proxy是代理的句柄,request.HTTPHandler也是一个句柄,据此构造了一个opener。install_opener安装全局的opener,这样就可以使用urlopen来打开网页了。
- 如果不调用install_opener(),则需要调用opener.open()来打开
- 代理的ip和端口可以在http://www.xicidaili.com/获取
1.6.4 打印日志
构造HTTPHandler或者HTTPSHandler对象的时候,设置debuglevel=1,即可,1.6.3的代码只需要修改
opener = request.build_opener(proxy,request.HTTPHandler)
为
opener = request.build_opener(proxy,request.HTTPHandler(debuglevel=1))
即可
这样日志就会打印在控制台中
1.6.5 异常处理
用到error模块,文档地址
主要就是用try except 来捕获错误
# -*- coding: utf-8 -*-
from urllib import request
from urllib import error
try:
request.urlopen("http://blog.csdn.com")
except error.HTTPError as e:
print(e.code)
print(e.reason)
except error.URLError as e:
print(e.reason)
HTTPError 是 URLError的子类,有code成员,所以要写成上面的形式。
http的常用错误码:
代码 | 英文 | 中文含义 |
---|---|---|
200 | OK | 一切正常 |
301 | Moved Permanently | 永久重定向 |
302 | Found | 临时重定向到资源 |
304 | Not Modified | 请求的资源没有更新 |
400 | Bad Request | 非法请求 |
401 | Unauthorized | 请求未经授权 |
403 | Forbidden | 禁止访问 |
404 | Not Found | 没有找到对应页面 |
500 | Internal Server Error | 服务器内部出现错误 |
501 | Not Implement | 服务器不支持当前请求 |
1.7 总结
1.7.1 URL和域名
超文本传输协议统一资源定位符(url)将从因特网获取信息的四个基本元素包括在一个简单的地址中:
- 传送协议; 2. 服务器; 3. 端口号; 4. 路径。
典型的统一资源定位符看上去是这样的:
其中:
- https,是协议;
- www.baidu.com,是服务器;
- 80,是服务器上的网络端口号(这里默认不填);
- /s,是路径;
- ?rsv_bp=0&rsv_sug2=0&ie=utf8&word=url%E5%9C%B0%E5%9D%80%E6%A0%BC%E5%BC%8F&tn=99455684_hao_pg,是询问。
www 是万维网的服务器,是网络名。baidu.com是在网络服务器上注册的主机名,默认端口是80。不加www是一级域名,加了就是二级域名,www只是声明提供的是web服务。
1.7.2 urllib及常用的函数总结
urllib由四个子模块组成
- request 负责打开和读取url
- error 负责获取request的错误
- parse 负责解析url
- robotparse 负责解析robot.txt文件,即爬虫协议
低端常用的是前三个模块,最重要的是第一个。
request模块的常用函数和常用用法
- urlopen(url , timeout) ,使用全局的opener,根据url对象打开一个网页,返回一个响应对象,调用响应对象的read,readline或readlines函数就可以获取内容。
- urlretrieve(url , path) ,直接将url保存在本地路径中
- build_opener(handler,…) , 使用句柄构造opener对象, 句柄可以是代理设置的句柄,如ProxyHandler的返回对象,HTTPHandler对象等,可以并排,HTTPHandler(debuglevel=1)可以打印日志。
- opener.open() ,和urlopen()功能一样,只不过是设置不同。
- opener_install(opener) , 把opener设置为全局的opener,这样就可以直接调用urlopen()来使用opener的设置了。
- Request(url,data=postdata),构造url请求对象,可以调用add_header(key,value)来添加http头,data参数可以是post的表单对象
- ProxyHandler({‘http’:proxy_addr}) 设置代理地址,返回代理句柄
error的使用
- URLError
- HTTPError
parse的使用
quote(str)
unquote(str) 编码与反编码
urlencode( ) 构造表单数据
postdata = parse.urlencode({ "name": "ceo@iqianyue.com", "pass": "aA1234567" }).encode('utf-8') req = request.Request(urladd, data=postdata)