urllib
import urllib.request
response = urllib.request.urlopen('https://blog.csdn.net/liumoude6/article/details/88074565?ops_request_misc=%257B%2522request%255Fid%2522%253A%2522161944009816780261994210%2522%252C%2522scm%2522%253A%252220140713.130102334..%2522%257D&request_id=161944009816780261994210&biz_id=0&utm_medium=distribute.pc_search_result.none-task-blog-2~all~sobaiduend~default-1-88074565.pc_search_result_before_js&utm_term=urllib.error.HTTPError%3A+HTTP+Error+403%3A+Forbidden')
print(response.read())
print(response.status) #200
request
是基本的HTTP请求模块,只需要传入URL以及额外的参数就能像浏览器一起。
urllib.request.urlopen()
方法相当于模拟一个浏览器进行请求发起的过程(可以尝试打开此网址,可能会解决一些你的问题)。
可以使用read()
方法去读取数据,可以使用status
获取响应的状态码。
headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36'}
url = 'https://www.bilibili.com/'
req= urllib.request.Request(url = url,headers = headers)
response = urllib.request.urlopen(req)
print(response.read())
由于urlopen()
方法太过简单,我们需要搭建更复杂的请求以防止被认为是爬虫从而被阻挡,我们可以采用Request
类来构建,他主要需要传入url
,headers
等几个参数。url
就是网址,headers
是一个字典,就是请求头,可以通过直接构造,也可以通过add_header()
方式来构造。即等效于下面:
url = 'https://www.bilibili.com/'
req= urllib.request.Request(url = url)
req.add_header('User-Agent','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/90.0.4430.85 Safari/537.36')
response = urllib.request.urlopen(req)
print(response.read())
Handler与代理、cookies等在这里不多做叙述,以后会专门针对这些进行详细的解答。
处理异常
import urllib.request
import urllib.error
try:
response = urllib.request.urlopen('https://www.bilibili.com/')
except urllib.error.URLError as e:
print(e.reason) #Forbidden
URLError
类来自urllib
库的error
模块,由request
模块产生的异常都可以通过捕获这个类来解决。
上面我们由于未添加请求头的基本结构,直接访问网址会被禁止访问,使用try except
方式来捕获,最后不会报错,得到一个Forbidden
的结果,显示为禁止访问。
try:
response = urllib.request.urlopen('https://www.bilibili.com/')
except urllib.error.HTTPError as e:
print(e.reason,e.code,e.headers,sep='\n') #Forbidden
# Forbidden
# 403
# Date: Mon, 26 Apr 2021 13:12:15 GMT
# Content-Type: text/html
# Transfer-Encoding: chunked
# Connection: close
# Server: openresty
# ETag: W/"5f9a3b2b-dca"
HTTPError是URLError的子类,专门用来处理HTTP请求错误,由于是子类,可以先判断是不是子类的错误,再用URLError来判断父类的错误。
try:
response = urllib.request.urlopen('https://www.bilibili.com/')
except urllib.error.HTTPError as e:
print(e.reason,e.code,e.headers,sep='\n')
except urllib.error.URLError as e:
print(e.reason)
解析链接
result = urllib.parse.urlparse('https://www.bilibili.com/anime/?spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2')
print(result)
#ParseResult(scheme='https', netloc='www.bilibili.com', path='/anime/', params='', query='spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2', fragment='')
parse
模块是来定义处理URL的标准接口,例如实现URL的抽取合并以及链接转换。
urlparse()
可以实现URL的识别和分段。我们通过上面的例子就可以看到一个URL有哪几部分组成。
scheme
代表协议,在://之前
netloc
代表域名
path
代表访问路径
params
代表参数,上面的例子没有参数
query
代表查询条件
fragment
代表锚点
scheme://netloc/path;params?query#fragment
就是一个标准的链接格式。
此模块还有许多对链接的拆分合并方法:
urlunparse()
:接收一个长度是6的可迭代对象,来构造一个URL
data = ['https','www.bilibili.com','anime','','spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2','']
print(urllib.parse.urlunparse(data))
#https://www.bilibili.com/anime?spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2
urlsplit()
与urlunsplit()
与上面相似,不同之处此处不多解释
print(urllib.parse.urljoin('https://www.bilibili.com/','/anime/?spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2'))
#https://www.bilibili.com/anime/?spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2
print(urllib.parse.urljoin('https://www/baidu.com/','https://www.bilibili.com/anime/?spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2'))
#https://www.bilibili.com/anime/?spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2
print(urllib.parse.urljoin('https://www.baidu.com/s?wd=XX&rsv_spt=1&rsv_iqid=0xb65f139500095a29&issp=1&f=8&rsv_bp=1&rsv_idx=2&ie=utf-8&rqlang=cn&tn=baiduhome_pg&rsv_enter=1&rsv_dl=tb&rsv_btype=t&rsv_t=39d1WRj4B4dWYbZWVa87cySVfCRzeucRfqQ9uNFjoC6FqSzPYx5WlPaNwoUZ8NMUrKwm&oq=%25E9%2597%25B2%25E9%25B1%25BC%25E7%259A%2584%25E5%259B%25BE%25E4%25B9%25A6%25E5%259B%259E%25E6%2594%25B6%25E7%25BB%2599%25E9%2592%25B1%25E5%2590%2597&rsv_pq=bbe37ff500099240&rsv_sug3=4&rsv_sug1=3&rsv_sug7=101&rsv_sug2=0&inputT=860&rsv_sug4=860','https://www.bilibili.com/anime/?spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2'))
#https://www.bilibili.com/anime/?spm_id_from=333.999.b_696e7465726e6174696f6e616c486561646572.2
urljoin()
方法通过传入两个链接,如果scheme
、netloc
和path
在新链接不存在,就补充到老链接里。如果新链接存在,就使用新链接的部分,老链接的params
、query
和fragment
是不起作用的。
还有一个常用的urlencode()
方法,有兴趣的自行查找。
requests
import requests
r = requests.get('http://www.bilibili.com')
print(r.text)
print(r.status_code)
urlopen()
是以GET方式请求网页的,而requests中直接使用get()
方法即可。
其他例如加入请求头这些方法大致和request相同,使用时如遇到问题请自行查阅相关资料。
import requests
headers = {'Cookie':'''_uuid=B84D79AD-21FC-1C1F-8228-3300EE9E9FD285407infoc; buvid3=02A4CA9D-AA9D-4B58-8EC2-46A04E3D27B8143072infoc; sid=6qugol4f; DedeUserID=8345645; DedeUserID__ckMd5=374e2bcce2a88621; SESSDATA=a784a2e4,1622980173,c6050*c1; bili_jct=f675b3879694654d91e8c8d2a195852b; CURRENT_FNVAL=80; blackside_state=1; rpdid=|(m)Y)RumuJ0J'uY|~Rk)YY~; LIVE_BUVID=AUTO3516074286958829; fingerprint3=b8803a5c632e26d031dd4dedbd618e8c; buivd_fp=02A4CA9D-AA9D-4B58-8EC2-46A04E3D27B8143072infoc; buvid_fp=02A4CA9D-AA9D-4B58-8EC2-46A04E3D27B8143072infoc; fingerprint=b22dd0f194cb3158b579ba51ccbc72bd; fingerprint_s=2f3686486d19968b6b5965c93bfb22f3; buvid_fp_plain=02A4CA9D-AA9D-4B58-8EC2-46A04E3D27B8143072infoc; CURRENT_QUALITY=116; Hm_lvt_8a6e55dbd2870f0f5bc9194cddf32a02=1619242625; bp_video_offset_8335502=517958929755062675; PVID=1'''
}
r = requests.get('http://www.bilibili.com/',headers = headers)
print(r.text)
可以使用添加Cookie的方法来维持登入状态。
import requests
s = requests.Session()
s.get('http://httpbin.org/cookies/set/number/123456789')
r = s.get('http://httpbin.org/cookies')
print(r.text)
我们也可以用Session()
方法来维持一个对话,这样就不用每次都担心Cookies的问题。
requests还有许多好用的方法,这里篇幅有限,需要学习的朋友可以参考站内大佬们的文章,这里就暂时没了~~~