-
Python3 urllib库和requests库
2019-01-03 22:19:471. Python3 使用urllib库请求网络 1.1 基于urllib库的GET请求 请求百度首页www.baidu.com ,不添加请求头信息: 1 import urllib.requests 2 3 4 def get_page(): 5 url = 'http://www.baidu.com/' ...1. Python3 使用urllib库请求网络
1.1 基于urllib库的GET请求
请求百度首页www.baidu.com ,不添加请求头信息:
1 import urllib.requests 2 3 4 def get_page(): 5 url = 'http://www.baidu.com/' 6 res = urllib.request.urlopen(url=url) 7 page_source = res.read().decode('utf-8') 8 print(page_source) 9 10 11 if __name__ == '__main__': 12 get_page()
输出显示百度首页的源码。但是有的网站进行了反爬虫设置,上述代码可能会返回一个40X之类的响应码,因为该网站识别出了是爬虫在访问网站,这时需要伪装一下爬虫,让爬虫模拟用户行为,给爬虫设置headers(User-Agent)属性,模拟浏览器请求网站。
1.2 使用User-Agent伪装后请求网站
由于urllib.request.urlopen() 函数不接受headers参数,所以需要构建一个urllib.request.Request对象来实现请求头的设置:
1 import urllib.request 2 3 4 def get_page(): 5 url = 'http://www.baidu.com' 6 headers = { 7 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' 8 } 9 request = urllib.request.Request(url=url, headers=headers) 10 res = urllib.request.urlopen(request) 11 page_source = res.read().decode('utf-8') 12 print(page_source) 13 14 15 if __name__ == '__main__': 16 get_page()
添加headers参数,来模拟浏览器的行为。
1.3 基于urllib库的POST请求,并用Cookie保持会话
登陆ChinaUnix论坛,获取首页源码,然后访问一个文章。首先不使用Cookie看一下什么效果:
1 import urllib.request 2 import urllib.parse 3 4 5 def get_page(): 6 url = 'http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LcN2z' 7 headers = { 8 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' 9 } 10 data = { 11 'username': 'StrivePy', 12 'password': 'XXX' 13 } 14 postdata = urllib.parse.urlencode(data).encode('utf-8') 15 req = urllib.request.Request(url=url, data=postdata, headers=headers) 16 res = urllib.request.urlopen(req) 17 page_source = res.read().decode('gbk') 18 print(page_source) 19 20 url1 = 'http://bbs.chinaunix.net/thread-4263876-1-1.html' 21 res1 = urllib.request.urlopen(url=url1) 22 page_source1 = res1.read().decode('gbk') 23 print(page_source1) 24 25 26 if __name__ == '__main__': 27 get_page()
搜索源码中是否能看见用户名StrivePy,发现登陆成功,但是再请求其它文章时,显示为游客状态,会话状态没有保持。现在使用Cookie看一下效果:
1 import urllib.request 2 import urllib.parse 3 import http.cookiejar 4 5 6 def get_page(): 7 url = 'http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LcN2z' 8 headers = { 9 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' 10 } 11 data = { 12 'username': 'StrivePy', 13 'password': 'XXX' 14 } 15 postdata = urllib.parse.urlencode(data).encode('utf-8') 16 req = urllib.request.Request(url=url, data=postdata, headers=headers) 17 # 创建CookieJar对象 18 cjar = http.cookiejar.CookieJar() 19 # 以CookieJar对象为参数创建Cookie 20 cookie = urllib.request.HTTPCookieProcessor(cjar) 21 # 以Cookie对象为参数创建Opener对象 22 opener = urllib.request.build_opener(cookie) 23 # 将Opener安装位全局,覆盖urlopen函数,也可以临时使用opener.open()函数 24 urllib.request.install_opener(opener) 25 res = urllib.request.urlopen(req) 26 page_source = res.read().decode('gbk') 27 print(page_source) 28 29 url1 = 'http://bbs.chinaunix.net/thread-4263876-1-1.html' 30 res1 = urllib.request.urlopen(url=url1) 31 page_source1 = res1.read().decode('gbk') 32 print(page_source1) 33 34 35 if __name__ == '__main__': 36 get_page()
结果显示登陆成功后,再访问其它文章时,显示为登陆状态。若要将Cookie保存为文件待下次使用,可以使用MozillaCookieJar对象将Cookie保存为文件。
1 import urllib.request 2 import urllib.parse 3 import http.cookiejar 4 5 6 def get_page(): 7 url = 'http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LcN2z' 8 headers = { 9 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' 10 } 11 data = { 12 'username': 'StrivePy', 13 'password': 'XXX' 14 } 15 postdata = urllib.parse.urlencode(data).encode('utf-8') 16 req = urllib.request.Request(url=url, data=postdata, headers=headers) 17 filename = 'cookies.txt' 18 # 创建CookieJar对象 19 cjar = http.cookiejar.MozillaCookieJar(filename) 20 # 以CookieJar对象为参数创建Cookie 21 cookie = urllib.request.HTTPCookieProcessor(cjar) 22 # 以Cookie对象为参数创建Opener对象 23 opener = urllib.request.build_opener(cookie) 24 # 临时使用opener来请求 25 opener.open(req) 26 # 将cookie保存为文件 27 cjar.save(ignore_discard=True, ignore_expires=True)
会在当前工作目录生成一个名为cookies.txt的cookie文件,下次就可以不用登陆(如果cookie没有失效的话)直接读取这个文件来实现免登录访问。例如不进行登陆直接访问其中一篇文章(没登陆也可以访问,主要是看抬头是不是登陆状态):
1 import http.cookiejar 2 3 4 def get_page(): 5 url1 = 'http://bbs.chinaunix.net/thread-4263876-1-1.html' 6 filename = 'cookies.txt' 7 cjar = http.cookiejar.MozillaCookieJar(filename) 8 cjar.load(ignore_discard=True, ignore_expires=True) 9 cookie = urllib.request.HTTPCookieProcessor(cjar) 10 opener = urllib.request.build_opener(cookie) 11 res1 = opener.open(url1) 12 page_source1 = res1.read().decode('gbk') 13 print(page_source1) 14 15 16 if __name__ == '__main__': 17 get_page()
结果显示是以登陆状态在查看这篇文章。
1.4 基于urllib库使用代理请求
使用代理可以有效规避爬虫被封。
1 import urllib.request 2 3 4 def proxy_test(): 5 url = 'http://myip.kkcha.com/' 6 headers = { 7 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' 8 } 9 request = urllib.request.Request(url=url, headers=headers) 10 proxy = { 11 'http': '180.137.232.101:53281' 12 } 13 # 创建代理Handler对象 14 proxy_handler = urllib.request.ProxyHandler(proxy) 15 # 以Handler对象为参数创建Opener对象 16 opener = urllib.request.build_opener(proxy_handler) 17 # 将Opener安装为全局 18 urllib.request.install_opener(opener) 19 response = urllib.request.urlopen(request) 20 page_source = response.read().decode('utf-8') 21 print(page_source) 22 23 24 if __name__ == '__main__': 25 proxy_test()
抓取到的页面应该显示代理IP,不知道什么原因,有时候能正常显示,有时候跳转到有道词典广告页!!!问题有待更进一步研究
2. Python3 使用requsets库访问网络
2.1 基于requests库的GET请求
以GET方式请求http://httpbin.org测试网站。
1 import requests 2 3 4 def request_test(): 5 url = 'http://httpbin.org/get' 6 response = requests.get(url) 7 print(type(response.text), response.text) 8 print(type(response.content), response.content) 9 10 11 if __name__ == '__main__': 12 request_test()
直接得到响应体。
1 <class 'str'> {"args":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Connection":"close","Host":"httpbin.org","User-Agent":"python-requests/2.18.4"},"origin":"121.61.132.191","url":"http://httpbin.org/get"} 2 3 <class 'bytes'> b'{"args":{},"headers":{"Accept":"*/*","Accept-Encoding":"gzip, deflate","Connection":"close","Host":"httpbin.org","User-Agent":"python-requests/2.18.4"},"origin":"121.61.132.191","url":"http://httpbin.org/get"}\n
在GET方法中传递参数的三种方式:
- 将字典形式的参数用urllib.parse.urlencode()函数编码成url参数:
1 http://httpbin.org/key1=value1&key2=value2
- 直接在urllib.request.get()函数中使用params参数:
1 import requests 2 3 if __name__ == '__main__': 4 payload = { 5 'key1': 'value1', 6 'key2': 'value2' 7 } 8 response = requests.get('http://httpbin.org/get', params=payload) 9 print(response.url)
1 http://httpbin.org/key1=value1&key2=value2
- url直接包含参数:
1 http://httpbin.org/get?key2=value2&key1=value1
2.2 基于requests库的POST请求,并用session保持会话
登陆ChinaUnix论坛,获取首页源码,然后访问一个文章。首先不使用Session看一下什么效果:
1 import requests 3 4 5 def get_page(): 6 url = 'http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LcN2z' 7 headers = { 8 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' 9 } 10 data = { 11 'username': 'StrivePy', 12 'password': 'XXX' 13 } 14 response = requests.post(url=url, data=data, headers=headers) 15 page_source = response.text 16 print(response.status_code) 17 print(page_source) 18 19 url1 = 'http://bbs.chinaunix.net/thread-4263876-1-1.html' 20 response1 = requests.get(url=url1, headers=headers) 21 page_source1 = response1.text 22 print(response1.status_code) 23 print(page_source1) 24 25 26 if __name__ == '__main__': 27 get_page()
结果显示访问其它文章时为游客模式。接下来用session来维持会话看一下效果:
1 import requests 2 3 4 def get_page(): 5 url = 'http://bbs.chinaunix.net/member.php?mod=logging&action=login&loginsubmit=yes&loginhash=LcN2z' 6 headers = { 7 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' 8 } 9 data = { 10 'username': 'StrivePy', 11 'password': 'XXX' 12 } 13 session = requests.session() 14 response = session.post(url=url, data=data, headers=headers) 15 page_source = response.text 16 print(response.status_code) 17 print(page_source) 18 19 url1 = 'http://bbs.chinaunix.net/thread-4263876-1-1.html' 20 response1 = session.get(url=url1, headers=headers) 21 page_source1 = response1.text 22 print(response1.status_code) 23 print(page_source1) 24 25 26 if __name__ == '__main__': 27 get_page()
结果显示访问其它文章时,显示为登陆状态,会话保持住了。使用session的效果类似于urllib库临时使用opener或者将opener安装为全局的效果。
2.3 基于requests库使用代理请求
在requests库中使用代理:
1 import requests 2 3 4 def proxy_test(): 5 url = 'http://myip.kkcha.com/' 6 headers = { 7 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.146 Safari/537.36' 8 } 9 proxy = { 10 'https': '61.135.217.7: 80' 11 } 12 response = requests.get(url=url, headers=headers, proxies=proxy) 13 print(response.text) 14 15 16 if __name__ == '__main__': 17 proxy_test()
- 将字典形式的参数用urllib.parse.urlencode()函数编码成url参数:
-
爬虫学习打卡1——urllib库和requests库
2018-08-03 18:20:04requests库 环境:Anaconda3(python3.5) urllib库 使用urllib构建一个请求和响应模型 import urllib strUrl=&amp;amp;quot;https://www.baidu.com/&amp;amp;quot; response=urllib.request...写在前面的话:每一个实例的代码都会附上相应的代码片或者图片,保证代码完整展示在博客中。最重要的是保证例程的完整性!!!方便自己也方便他人~欢迎大家交流讨论~
环境:Anaconda3(python3.5)
urllib库
使用urllib构建一个请求和响应模型
import urllib strUrl="https://www.baidu.com/" response=urllib.request.urlopen(strUrl) print (response.read())
运行返回:
runfile('F:/Python/SPIDER/1.py', wdir='F:/Python/SPIDER') b'<html>\r\n<head>\r\n\t<script>\r\n\t\tlocation.replace(location.href.replace("https://","http://"));\r\n\t</script>\r\n</head>\r\n<body>\r\n\t<noscript><meta http-equiv="refresh" content="0;url=http://www.baidu.com/"></noscript>\r\n</body>\r\n</html>'
这里有一个python3和python2的区别——
python2中是import urllib2,但是python3没有urllib2即使在cmd中pip3 install urllib2也无法安装 urllib2。
原因:python 3.X版本是不需要安装urllib2包的,urllib和urllib2包集合成在一个包了
那现在问题是:
在python3.x版本中,如何使用:urllib2.urlopen()?
答:
import urllib.request
response=urllib.request.urlopen(“http://www.baidu.com“)post数据传送方式
import urllib import urllib.request import urllib.parse myData={} myData['key1']='value1' myData['key2']='value2' myNewData=urllib.parse.urlencode(myData).encode(encoding='UTF8')#转换格式 url="https://www.baidu.com" req=urllib.request.Request(url,myNewData)#新建req变量表示一个请求 respon=urllib.request.urlopen(req)#新建respon变量表示对应req请求的一个响应 page=respon.read().decode("utf8")#让爬到的页面为Html代码 print(req) print(page)
其中没有
page=respon.read().decode("utf8")
时,你爬到的非常乱
有了上面的格式转换,就成下面的样子,和你在网页中右键——审查元素看到的是一样的格式
Get方式传送数据
import urllib import urllib.request import urllib.parse myData={} myData['key1']='value1' myData['key2']='value2' myNewData=urllib.parse.urlencode(myData)#转换格式 url="https://passport.baidu.com/v2/?login"#百度登录界面 newUrl=url+'?'+myNewData req=urllib.request.Request(newUrl)#新建req变量表示一个请求 respon=urllib.request.urlopen(req)#新建respon变量表示对应req请求的一个响应 page=respon.read().decode("utf8")#让爬到的页面为Html代码 print(newUrl) print(page)
运行结果:
其中要注意:get传送数据最主要的不同是直接修改了请求的URL,使你要传送的数据在URL上体现出来,即https://passport.baidu.com/v2/?login?key2=value2&key1=value1
而post是将数据作为的一个参数传入,即urllib.request.Request(url,myNewData)
requests库
关于如何使用requests模块向网站发送http请求,获取到网页的HTML数据。
get和post传送数据import requests myData={"key1":"value1","key2":"value2"}#要传递的数据 response1=requests.get("https://www.baidu.com/")#无参的get请求 response2=requests.get("https://www.baidu.com/",params=myData)#有参的get请求 response3=requests.post("https://www.baidu.com/")#无参的post请求 response4=requests.post("https://www.baidu.com/",data=myData)#有参的post请求 print(response1.text) print(response2.text) print(response3.text) print(response4.text)
-
Python爬虫之urllib库和requests库的基本使用
2020-07-27 19:35:17在Python3中,有urllib库来实现请求的发送(将Python2中的urllib2已经统一至urllib库中)。 对于urllib库的疑问可以参照官网说明了解:https://docs.python.org/3/library/urllib.html urllib库 urllib库是python...Python爬虫之基本库urllib的使用
在Python3中,有urllib库来实现请求的发送(将Python2中的urllib2已经统一至urllib库中)。
对于urllib库的疑问可以参照官网说明了解:
https://docs.python.org/3/library/urllib.html
urllib库
urllib库是python内置的HTTP请求库,包含四个模块:
- request:最基本的HTTP请求模块,可以用来模拟发送请求。
- error:异常处理模块,如果出现请求错误,可以对这些异常进行捕获,防止程序意外终止。
- parse:一个工具模块,提供了许多URL的处理方法,如拆分、合并等。
- robotparser:主要用来识别网站的robot.txt文件。
发送请求
urlopen()
urllib.request的模块提供了最基本的构造HTTP请求的方法,利用它可以模拟浏览器的一个请求发起过程。
首先给出urlopen()方法的API:
urllib.request.urlopen
(url, data=None, [timeout, ]***, cafile=None, capath=None, cadefault=False, context=None),后面会详细介绍各项参数意义。下面我们简单的调用下urlopen()方法:
import urllib.request response = urllib.request.urlopen('https://www.python.org') print(response.read().decode('utf-8'))
可以得到如下输出:
<!doctype html> <!--[if lt IE 7]> <html class="no-js ie6 lt-ie7 lt-ie8 lt-ie9"> <![endif]--> <!--[if IE 7]> <html class="no-js ie7 lt-ie8 lt-ie9"> <![endif]--> <!--[if IE 8]> <html class="no-js ie8 lt-ie9"> <![endif]--> <!--[if gt IE 8]><!--><html class="no-js" lang="en" dir="ltr"> <!--<![endif]--> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> ....#省略 </body> </html>
接下来,我们看看
urllib.request.urlopen()
方法返回的是个是什么import urllib.request response = urllib.request.urlopen('https://www.python.org') print(type(response)) #打印response的类型
输出如下:
<class 'http.client.HTTPResponse'>
可以发现,返回的是一个HTTPResponse类型的对象。HTTPResponse类型的对象包含read()、readinto()、hetheader(name)、fileno()等方法和status等属性。如下打印了HTTPResponse类型的方法返回及其status属性。
import urllib.request response = urllib.request.urlopen('https://www.python.org') print(response.status) print(response.getheaders())
输出了状态码和相应的头信息,如下:
200 [('Connection', 'close'), ('Content-Length', '48730'), ('Server', 'nginx'), ('Content-Type', 'text/html; charset=utf-8'), ('X-Frame-Options', 'DENY'), ('Via', '1.1 vegur'), ('Via', '1.1 varnish'), ('Accept-Ranges', 'bytes'), ('Date', 'Mon, 27 Jul 2020 07:55:36 GMT'), ('Via', '1.1 varnish'), ('Age', '2423'), ('X-Served-By', 'cache-bwi5134-BWI, cache-hkg17928-HKG'), ('X-Cache', 'HIT, HIT'), ('X-Cache-Hits', '30, 2173'), ('X-Timer', 'S1595836536.216510,VS0,VE0'), ('Vary', 'Cookie'), ('Strict-Transport-Security', 'max-age=63072000; includeSubDomains')]
输出状态码200代表访问成功,常见的状态码还有404(页面未找到)、400(服务器无法解析请求)、**500(服务器遇到错误)**等。
urlopen()——data参数
data参数是可选的,若添加此参数,需要使用bytes()方法将参数转化为bytes类型。并且请求方式将变为POST。
为将其转化为bytes类型,我们可以用bytes()方法,同时利用urllib.parse模块里的urlencode()方法将参数字典转化为字符串作为第一个参数;第二个参数是指定编码格式。
import urllib.request import urllib.parse mydict = { 'name':'Small_Fish'} mydata = bytes(urllib.parse.urlencode(mydict),encoding='utf8') response = urllib.request.urlopen('http://httpbin.org/post',data=mydata)#该链接可以用来测试POST请求 print(response.status) print(response.read())
输出如下:
200 b'{\n "args": {}, \n "data": "", \n "files": {}, \n "form": {\n "name": "Small_Fish"\n }, \n "headers": {\n "Accept-Encoding": "identity", \n "Content-Length": "15", \n "Content-Type": "application/x-www-form-urlencoded", \n "Host": "httpbin.org", \n "User-Agent": "Python-urllib/3.7", \n "X-Amzn-Trace-Id": "Root=1-5f1e8dbc-6aa88726e6a39100e23797ed"\n }, \n "json": null, \n "origin": "117.136.19.0", \n "url": "http://httpbin.org/post"\n}\n'
可见返回的内容的"form"即为我们传递的参数,表面了是模拟表单的提交方式,以POST方式传输数据。
urlopen()——timeout参数
timeout参数根据字面意义大家应该就能猜到其意义了,该参数用于设置超时时间(单位:s),当发出的请求超出了该时间依然没有得到相应时,就会抛出异常,我们可以用try-except来捕获异常。
import urllib.request import urllib.parse import urllib.error import socket if __name__ =="__main__": mydata = bytes(urllib.parse.urlencode({'name':'Small_Fish'}),encoding='utf8') try: response = urllib.request.urlopen('http://httpbin.org/post',data = mydata,timeout = 0.1)#设置超时时间为0.1s,当超过改时间没有得到相应将抛出异常 except urllib.error.URLError as e: if isinstance(e.reason,socket.timeout):#判断,如果异常原因是socket.timeout则打印TIME OUT print('TIME OUT')
输出如下:
TIME OUT
Request()
当请求中需要加入Headers等信息时,我们就需要用到更强大的Request类来构建请求。
API:class
urllib.request.Request
(url, data=None, headers={}, origin_req_host=None, unverifiable=False, method=None)下面直接来说参数吧:
- url:请求的URL
- data:同urlopen中的data,为bytes类型。如果是字典需要先用urllib.parse.urlencode()进行编码
- headers:请求头,是一个字典
- origin_req_host:请求方的host名称或IP地址
- unverifiable:表示请求是否是无法验证的,默认False。
- method:请求的方法(GET、POST、PUT等)
还是举一个实例:
import urllib.request import urllib.parse if __name__ == '__main__': url = 'http://httpbin.org/post' #参数URL headers = { 'User-Agent': 'Mozilla/4.0(compatible; MISE 5.5;Windows NT)', 'Host':'httpbin.org'}#参数Headers dict ={ 'name':'Small_Fish'} #参数data mydata = bytes(urllib.parse.urlencode(dict),encoding='utf-8') request =urllib.request.Request(url,data = mydata,headers = headers, method = 'POST') response = urllib.request.urlopen(request)#依然使用了urlopen() print(response.read().decode('utf8'))
输出如下:
{ "args": {}, "data": "", "files": {}, "form": { "name": "Small_Fish" }, "headers": { "Accept-Encoding": "identity", "Content-Length": "8", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "Mozilla/4.0(compatible; MISE 5.5;Windows NT)", "X-Amzn-Trace-Id": "Root=1-5f1e9458-03e22590f337243009a04b88" }, "json": null, "origin": "117.136.19.0", "url": "http://httpbin.org/post" }
观察发现我们成功设置了相应的data、headers、method,其中我们构造headers的"User-Agent"为"Mozilla/4.0(compatible; MISE 5.5;Windows NT)"是用来伪装成火狐浏览器。
同时,我们也发现我们依然用了urlopen(),只不过这次的参数不再是url,而是一个request类型的对象。
处理异常
URLError
URLError类来自urllib库的error模块,它继承自OSError类,是Error异常模块类的基类,由request模块产生的异常可以通过捕获这个类来处理。
from urllib import request, parse, error import urllib mydict = { 'name':'Small_Fish'} mydata = bytes(urllib.parse.urlencode(mydict),encoding='utf8') try: response = urllib.request.urlopen('http://sbsbsbsbsb.com',data=mydata,timeout=0.1) print(response.status) print(response.read()) except error.URLError as e: print(e.reason)
输出:
timed out
可以看到程序没有直接报错,而是打印出了异常信息,通过这样我们可以有效避免程序异常终止。
HTTPError
HTTPError异常类是URLError类的子类,专门用来处理HTTP请求错误。
HTTPError有三个属性:
- code:返回HTTP的状态码
- reason:返回错误的原因
- headers:返回请求头
from urllib import request, parse, error import urllib try: response = urllib.request.urlopen('https://a.com') print(response.status) except error.HTTPError as e: print(e.reason,e.code,e.Headers,sep='\n')
解析链接
urlparse()
API:
urllib.parse.urlparse(urlstring,scheme=' ',allow_fragment=True)
该方法可以实现URL的识别和分段。
from urllib.parse import urlparse res = urlparse('http://www.baidu.com/index/html;user?id=5#comment') print(type(res),res,sep='\n')
输出如下:
<class 'urllib.parse.ParseResult'> ParseResult(scheme='http', netloc='www.baidu.com', path='/index/html', params='user', query='id=5', fragment='comment')
返回的结果为ParseResult类型的一个对象,包含了6个部分scheme, netloc, path, params, query和 fragment
- scheme:协议(http、https)
- netloc:域名,第一个/符合前便是netloc
- path::访问路径
- params:参数, ;号后面便是params
- query:查询条件,?后是查询条件
- fragment:锚点,用于直接定位页面内部的下拉位置
因此我们得到了一个标准的链接格式:
scheme://netloc/path;params?query#fragment
urlunparse()
urlunparse()构造一个URL,接受的参数是一个可迭代对象,但必须长度为6.
from urllib.parse import urlunparse data = ['http','www.baidu.com','index.html','user','id=6','comment'] res = urlunparse(data) print(type(res),res,sep='\n')
输出如下:
<class 'str'> http://www.baidu.com/index.html;user?id=6#comment
返回的结果为str类型的一个对象,并且成功构造了相应的URL。
urlsplit()
urlsplit()与urlparse()非常相似,只不过不在单独解析params,只返回5个结果。
from urllib.parse import urlsplit res = urlsplit('http://www.baidu.com/index/html;user?id=5#comment') print(type(res),res,sep='\n')
输出如下:
<class 'urllib.parse.SplitResult'> SplitResult(scheme='http', netloc='www.baidu.com', path='/index/html;user', query='id=5', fragment='comment')
由结果可知uesr被加入path中了。
urlunsplit()
urlunsplit()构造一个URL,接受的参数是一个可迭代对象,但必须长度为,类似urlunparse()就不再放代码了。
urljoin()
urljoin()就是用一个链接(参数1)对另外一个新链接(参数2)缺失部分进行补充,最后返回结果。
from urllib.parse import urljoin res = urljoin('http://www.baidu.com/index.php?id=5#comment','//www.tianmao.com') print(res)
输出:
http://www.tianmao.com
urlencode()
urlencode()常常用于构造GET请求参数。
from urllib.parse import urlencode dicts = { 'name':'Small_Fish', 'years':21} base_url = 'http://www.baidu.com/' url = base_url + urlencode(dicts) print(url)
输出:
http://www.baidu.com/name=Small_Fish&years=21
这个方法非常常用。有时为了更加方便地构造参数,我们会事先用字典来表示。要转化为URL参数时,只需要调用方法就行。
quote()和unquote()
quote()该方法可以将内容转化为URL编码的格式。因为URL中带有中文参数时,可能会导致乱码的问题,利用此方法可以将中文转化为URL编码。
相应的unquote()可以对URL编码进行解码。
from urllib.parse import urlencode,quote,unquote name = '帅哥' base_url = 'http://www.baidu.com/' print(base_url+name) url = base_url +quote(name) print(url) print(unquote(url))
输出如下:
http://www.baidu.com/帅哥 http://www.baidu.com/%E5%B8%85%E5%93%A5 http://www.baidu.com/帅哥
如上便实现了编码和解码的过程。
Python爬虫之requests库的使用
requests库是在python3爬虫中相对于urllib库更强大的一个库,有了它我们可以轻松进行Cookies、登录验证、代理设置等操作。
requests库的安装
windows下在命令行窗口下输入
pip3 install requests
命令即可完成安装,非常简单。requests的GET请求
HTTP中最常见的就是GET请求,下面介绍一下利用requests构建GET请求的方法。
requests.get()
requests中以GET方式请求网页的方法就是get,是不是非常直观呢?(相对于urllib库)
如↓:
import requests response = requests.get('https://www.baidu.com') print(type(response)) print(response.status_code) print(response.text)
输出如下:
<class 'requests.models.Response'> 200 <!DOCTYPE html> <!--STATUS OK--><html> <head><meta http-equiv=content-type content=text/html;charset=utf-8><meta http-equiv=X-UA-Compatible content=IE=Edge><meta content=always name=referrer><link rel=stylesheet type=text/css href=https://ss1.bdstatic.com/5eN1bjq8AAUYm2zgoY3K/r/www/cache/bdorz/baidu.min.c ....#省略OTZ src=//www.baidu.com/img/gs.gif> </p> </div> </div> </div> </body> </html>
可见requests.get()返回的是一个Response类型的对象,同时也可以调用其状态码、内容等属性了解相应结果。
如果我们想向请求中添加参数,通过get()方法也可以很轻松实现:
import requests param = { 'name':'Small_Fish', 'years':21 } headers ={ 'User-Agent':'Mozilla/5.0', } response = requests.get('http://httpbin.org/get',params = param,headers=headers) print(type(response)) print(response.status_code) print(response.text)
输出如下:
<class 'requests.models.Response'> 200 { "args": { "name": "Small_Fish", "years": "21" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Host": "httpbin.org", "User-Agent": "Mozilla/5.0", "X-Amzn-Trace-Id": "Root=1-5f1fcc0b-b1818391d5a51ffc4dd76471" }, "origin": "117.136.19.0", "url": "http://httpbin.org/get?name=Small_Fish&years=21" }
requests的POST请求
另外一种比较常见的请求方式是POST请求,使用方法也非常简单。
import requests param = { 'name':'Small_Fish', 'years':'21' } response = requests.post('http://httpbin.org/post',data = param) print(response.text)
输出如下:
{ "args": {}, "data": "", "files": {}, "form": { "name": "Small_Fish", "years": "21" }, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip, deflate", "Content-Length": "24", "Content-Type": "application/x-www-form-urlencoded", "Host": "httpbin.org", "User-Agent": "python-requests/2.24.0", "X-Amzn-Trace-Id": "Root=1-5f1fcdba-bd70c740c324e9401d5cf270" }, "json": null, "origin": "117.136.19.0", "url": "http://httpbin.org/post" }
-
网络数据采集---urllib库和requests库
2020-04-22 22:33:23网络数据采集之urllib库 一、urllib urllib简介 urllib是python中一个功能强大用于操作URL,并在爬虫时经常用到的一个基础库,无需额外安装,默认已经安装到python中。 官方文档地址:请点击这里 urllib的四个子模块...网络数据采集之urllib库
一、urllib
urllib简介
urllib是python中一个功能强大用于操作URL,并在爬虫时经常用到的一个基础库,无需额外安装,默认已经安装到python中。
官方文档地址:请点击这里
urllib的四个子模块
Python中urllib库包括以下四个子模块,urllib库是python的内置HTTP请求库,urllib库是一个运用于URL的包(urllib is a package that collects several modules for working with URLs)
- urllib.request: 请求模块。用于访问和读取URLS(urllib.request for opening and reading URLs),就像在浏览器里输入网址然后回车一样,只需要给这个库方法传入URL和其他参数就可以模拟实现这个过程。
- urllib.error :异常处理模块。包括了所有urllib.request导致的异常(urllib.error containing the exceptions raised by urllib.request),我们可以捕捉这些异常,然后进行重试或者其他操作以确保程序不会意外终止。
- urllib.parse:解析模块。用于解析URLS(urllib.parse for parsing URLs),提供了很多URL处理方法,比如拆分、解析、合并、编码。
- urllib.robotparser:robots.txt解析模块。用于解析robots.txt文件(urllib.robotparser for parsing robots.txt files),然后判断哪些网站可以爬,哪些网站不可以爬。
使用urllib打开网页
最基本的方法打开网页—urlopen
urlopen进行简单的网站请求,不支持复杂功能如验证、cookie和其他HTTP高级功能,若要支持这些功能必须使用build_opener()函数返回的OpenerDirector对象。# 最基本的方法打开网页 from urllib.request import urlopen # 通过get方法请求url with urlopen("http://www.baidu.com") as f: # 默认返回的页面类型是bytes类型,bytes类型转换为字符串,decode方法 print(f.read(300).decode('utf-8')
携带data参数打开网页
# 携带data参数打开网页 from urllib.parse import urlencode from urllib.request import urlopen data = bytes(urlencode({'word': 'hello'}), encoding='utf-8') response = urlopen('http://httpbin.org/post', data=data) print(response.read().decode('utf-8'))
User-Agent伪装后请求网站
很多网站为了防止程序爬虫爬网站照成网站瘫痪,会需要携带一些headers头部信息才能访问, 我们可以通过urllib.request.Request对象指定请求头部信息。
User-Agent = 'Mozilla/4.0(compatibe;MSIE 5.5;Windows NT)' # 封装请求头部信息,模拟浏览器向服务器发起请求 request = Request("http://httpbin.org/post", headers={'User-Agent':User-Agent}) with urlopen(request) as f: # 默认返回的页面信息是bytes类型,bytes类型转换为字符串用decode方法 print(f.read(300).decode('utf-8'))
通过构建Request打开网页
from urllib.request import Request from urllib.request import urlopen from urllib.parse import urlencode url = 'http://httpbin.org/post' headers = { 'User-Agent': 'Mozilla/4.0(compatibe;MSIE 5.5;Windows NT)', 'Host': 'httpbin.org' } dict = {'name': 'Germey'} data = bytes(urlencode(dict), encoding='utf8') req = Request(url=url, data=data, headers=headers, method='POST') response = urlopen(req) print(response.read().decode('utf-8'))
网络数据采集之requests库
requests官方网址:点击这里
Requests is an elegant and simple HTTP library for Python, built for human beings.
相比较urllib模块,requests模块要简单很多,但是需要单独安装:- linux系统下的安装: pip install requests
requests库的八大主要方法:
方法 描述 requests.request( ) 构造一个请求,支持以下各种方法 requests.get( ) 向html页面提交get请求的方法,对应于HTTP的GET requests.post( ) 向html页面提交post请求的方法,对应于HTTP的POST requests.head( ) 获取html头部信息的主要方法,对应于HTTP的HEAD requests.put( ) 向html网页提交put请求的方法,对应于HTTP的PUT requests.options( ) 向html页面提交options请求的方法,对应于HTTP的OPTIONS requests.patch( ) 向html网页提交局部修改的请求,对应于HTTP的PATCH requests.delete( ) 向html网页提交删除的请求,对应于HTTP的DELETE 请求之后,服务器通过response返回数据,Response对象包含服务器返回的所有信息,也包含请求的Request信息。
response具体参数如下图:
属性 说明 r.status_code HTTP请求的返回状态,200表示成功,404表示失败 r.text HTTP响应内容的字符串形式,即url对应的页面内容 r.content( ) HTTP响应内容的二进制形式 r.encoding 从HTTP header中猜测响应内容的编码格式 r.apparent_encoding 从内容中分析出响应内容的编码格式(备选编码格式) 防止反爬1:添加headers–UserAgent
有些网站访问时必须带有浏览器等信息,如果不传入headers就会报错。
UserAgent是识别浏览器的一串字符串,相当于浏览器的身份证,在利用爬虫爬取网站数据时,频繁更换UserAgent可以避免触发相应的反爬机制。fake-useragent对频繁更换UserAgent提供了很好的支持,可谓防反爬利器。
# 首先导入UserAgent: from fake_useragent import UserAgent def add_headers(): user_agent = UserAgent().random # 将请求头部添加到 response = requests.get('http://127.0.0.1:5000', headers={'User-Agent':user_agent}) print(response) if __name__ == '__main__': add_headers()
防止反爬2:IP代理设置–proxies
在进行爬虫爬取时,有时候爬虫会被服务器屏蔽掉,这时候采用的方法主要有降低访问时间,通过代理IP访问。IP可以从网上抓取,或者某宝购买。
proxies = { "http": "http://127.0.0.1:9743", "https": "https://127.0.0.1:9743",} response = requests.get(url, proxies=proxies)
useragent和IP代理的结合使用:
import requests from fake_useragent import UserAgent us = UserAgent() proxies = { 'http':'http://163.125.75.233:9797', 'https':'https://182.92.220.212:8000' } response = requests.get('http://47.92.255.98:8000', headers={'User-Agent':us.random}, proxies=proxies) print(response) print(response.text)
爬虫应用小案例
京东商品信息爬取:
from urllib.error import HTTPError import requests from colorama import Fore from fake_useragent import UserAgent def down_page(url, params=None): try: ua = UserAgent() headers = {'User-Agent':ua.random} response = requests.get(url, params, headers=headers) except HTTPError as e: print(Fore.RED + '[-] 爬取网站%s失败:%s' %(url, e.reason)) return None else: return response.content def down_file(content=b'', filename='hello.html'): with open(filename, 'wb') as f: f.write(content) print(Fore.GREEN + '[+]写入文件%s成功' %(filename)) if __name__ == '__main__': url = 'https://item.jd.com/100012015170.html' html = down_page(url) down_file(content=html)
360搜索关键字提交
from urllib.error import HTTPError import requests from colorama import Fore from fake_useragent import UserAgent def down_page(url, params): try: ua = UserAgent() headers = { 'User-Agent':ua.random } response = requests.get(url, params, headers=headers) except HTTPError as e: print(Fore.RED + '[-]爬取网页%s失败:%s' %(url, e.reason)) return None else: return response.content # 二进制文件 def down_file(content=b'',filename='python.html'): with open(filename, 'wb') as f: f.write(content) print(Fore.GREEN + '[+]关键字写入文件%s成功......'%(filename)) if __name__ == '__main__': url = 'https://www.so.com/s' params = { 'q' : 'python' } down_file(content = down_page(url, params))
response = requests.get(url, params, headers=headers) 这里参数会自动填入访问的url网页,进行关键字查询。
-
【python&爬虫】快速入门urllib库和requests库
2020-05-25 21:27:26文章目录一.urllib库基本介绍二.urllib.request 请求模块1.urlopen方法参数解析1.1.发送get请求1.2.发送post请求(设置data参数)1.3.设置timeout参数1.4.HTTPResponse对象2.构造Request对象三.urllib.parse URL解析... -
python request和urllib_Python-网络请求urllib库和requests库
2020-12-03 05:30:091. urllib.request模块模块定义了身份验证、重定向、cookies等应用中打开Url(主要是HTTP)的函数和类。1)urlopen方法def urlopen(url, data=None, timeout=socket._GLOBAL_DEFAULT_TIMEOUT,*, cafile=None, capath=... -
Python的网络请求(urllib库和requests库)
2019-12-13 16:54:501.urllib库 —内置 urlopen函数: 创建一个表示远程url的类文件对象,然后像本地文件一样操作这个类文件对象来获取远程数据。 url:请求的url。 data:请求的data,如果设置了这个值,那么将变成post请求。 返回值:... -
Python爬虫第三课:Urllib库和Requests库的基本用法(二)
2020-09-12 17:42:54Requests是用python语言基于urllib编写的,采用的是Apache2 Licensed开源协议的HTTP库如果你看过上篇文章关于urllib库的使用,你会发现,其实urllib还是非常不方便的,而Requests它会比urllib更加方便,可以节约我们...