博主简介:博主是一个大二学生,主攻人工智能领域研究。感谢缘分让我们在CSDN相遇,博主致力于在这里分享关于人工智能,C++,python,爬虫等方面的知识分享。如果有需要的小伙伴,可以关注博主,博主会继续更新的,如果有错误之处,大家可以指正。
专栏简介:本专栏致力于研究python爬虫的实战,涉及了所有的爬虫基础知识,以及爬虫在人工智能方面的应用。文章增加了JavaScript逆向,网站加密和混淆技术,AST还原混淆代码,WebAssembly,APP自动化爬取,Android逆向等相关技术。同时,为了迎合云原生发展,同时也增加了基于Kubernetes,Docker,Prometheus,Grafana等云原生技术的爬虫管理和运维解决方案。
订阅专栏
博主分享:给大家分享一句我很喜欢的话:“每天多一点努力,不为别的,值为日后,能够多一些选择,选择舒心的日子,选择自己喜欢的人!”
目录
urlib的使用
urlib的简介
高级用法
requests的使用
总结
urlib的使用
urlib的简介
urlib作为python的一个库,利用它就可以实现HTTP的请求,而且不需要关心HTTP协议本身甚至更底层的实现。
注意:在python2中,有urlib和urlib2两个库来实现HTTP请求的发送。而在Python3中,urlib2库已经不存在,统一为urlib。
urlib是python内置的HTTP请求库,不需要额外安装,urlib库包含了以下四个模块:
①request:这是最基本的HTTP请求模块,可以模拟请求的发送。就像在浏览器中输入网址后按下回车,只需要传入参数即可。
②error:异常处理模块,如果出现异常,我们可以捕获这些异常,然后进行重试或其它操作。
③parse:一个工具模块,可以对URL进行解析,合并,拆分等。
④robotparse:主要用来识别网站的robots.txt文件,然后判断哪些网站可以爬,哪些不可以爬,但是用的比较少。
1.发送请求
urlopen:urlopen是request模块中的打开网址的函数,也就是发送请求,然后返回响应。
我们这里就以csdn官网的网址为例:
import urllib.request
URL='https://www.csdn.net/'
response=urllib.request.urlopen(URL)
print(response.read().decode('utf-8'))
由于博主所用的编译器是VS code,这里的显示结果会和pycharm有所区别,需要存储到html文件中才能 展示原有的网页源码。
我们得到的响应response是一个HTTPResponse对象,主要包含了read,readinto,getheader,getheaders,fileno等方法。同时包含了status,msg,version,reason,debuglevel,closed等属性。
import urllib.request
URL='https://www.csdn.net/'
response=urllib.request.urlopen(URL)
#print(response.read().decode('utf-8'))
print(type(response))
print(response.status)
print(response.getheaders())
print(response.getheader('Server'))
结果展示:
<class 'http.client.HTTPResponse'> 200 [('Date', 'Thu, 02 Feb 2023 05:05:42 GMT'), ('Content-Type', 'text/html; charset=utf-8'), ('Transfer-Encoding', 'chunked'), ('Connection', 'close'), ('Set-Cookie', 'acw_tc=2760828a16753143417275296e9ff014e190d9eaac93280ed2e9c0db434d2d;path=/;HttpOnly;Max-Age=1800'), ('Server', 'openresty'), ('Vary', 'Accept-Encoding'), ('Set-Cookie', 'uuid_tt_dd=10_19879412540-1675314353111-318560; Expires=Thu, 01 Jan 2025 00:00:00 GMT; Path=/; Domain=.csdn.net;'), ('Set-Cookie', 'dc_session_id=10_1675314353111.898938; Expires=Thu, 01 Jan 2025 00:00:00 GMT; Path=/; Domain=.csdn.net;'), ('set-cookie', 'csrfToken=Js40dDZ0Qy7cMwzKhIni5Iqu; path=/; secure'), ('X-Response-Time', '432'), ('x-xss-protection', '1; mode=block'), ('x-content-type-options', 'nosniff'), ('x-download-options', 'noopen'), ('x-readtime', '432'), ('Strict-Transport-Security', 'max-age=31536000')] openresty
当然除了传递这些参数,urlopen函数还有其他参数:
1.data参数: data参数是可选的,需要使用bytes方法将参数转化为字节流编码格式的内容,即bytes类型,另外,如果传递了这个参数,那么它的请求方式就不再是GET、,只能是POST。
import urllib.request import urllib.parse URL='https://baidu.com' data=bytes(urllib.parse.urlencode({'name':'germey'}),encoding='utf-8') response=urllib.request.urlopen(url=URL,data=data) print(response.read().decode('utf-8'))
2.timeout参数: 这个参数是用来设置超出时间的,设置一个时间,代表时间限制,如果超出了这个时间服务器没有响应,不那么就会抛出错误。
import urllib.request import urllib.error import socket url='https://baidu.com' try: response=urllib.request.urlopen(url=url,timeout=0.1) except urllib.error.URLError as e: if isinstance(e.reason,socket.timeout): print("Time Out") else: print('Yes')
除了上面的参数,还有context参数,该参数必须是ssl.SSLContext,用来指定SSL的的设置。此外还有cafile,capath两个参数分别用来指定CA证书和其路径,这两个在请求HTTPS链接时会有用。
cadefault已经被弃用,默认为False。
当然除了urlopen可以打开网页,Request类也可以打开,和urlopen相比,其功能更加强大,这里我们来介绍一下Request如何使用:
我们要是想使用Request类,那么就要构建Request类,这就需要很多参数:
class urllib.request.Request(url,data=None,headers={},origin_req_host=None,unverifiable=False,method=None)
第一个参数url用于指定网址,这是必传参数,其他的都是可选参数。
data参数和前面的data参数一样,第三个参数headers是一个字典,这是请求头,我们在构建请求头的时候,直接可以通过headers参数构建,也可以通过调用请求实例的add_header方法添加。
添加请求头headers最常见的方法就是通过修改User-Agent来伪装浏览器。我们可以修改此值来伪装,如果我们要伪装火狐浏览器,就可以把User-Agent设置为:
Mozilla/5.0 (X11;U;Linux i686) Gecko/20071127 Firefox/2.0.0.11
第四个参数origin_req_host是请求方的IP地址或host名称
第五个参数则是表示请求是否是无法验证的。
第六个参数method是一个字符串类型,表示请求的方法,例如GET,POST等。
from urllib import request,parse
url='https://www.baidu.com'
headers={
'User-Agent':'Mozilla/5.0 (X11;U;Linux i686) Gecko/20071127 Firefox/2.0.0.11'
}
data=bytes(parse.urlencode({'name':'germey'}),encoding='utf-8')
req=request.Request(url=url,data=data,headers=headers)
response=request.urlopen(req)
print(response.read().decode('utf-8'))
使用add_header()函数的代码:
#使用add_header()函数
from urllib import request,parse
url='https://www.baidu.com'
data=bytes(parse.urlencode({'name':'germey'}),encoding='utf-8')
req=request.Request(url=url,data=data)
req.add_header('User-Agent','Mozilla/5.0 (X11;U;Linux i686) Gecko/20071127 Firefox/2.0.0.11')
response=request.urlopen(req)
print(response.read().decode('utf-8'))
高级用法
我们前面学习了爬虫的简单知识,也就是如何去打开网页,现在,如果我们要进行一些高级操作,就需要使用更强大的工具handler,简而言之,handler就是处理登陆验证的,处理cookie的,处理代理设置的。利用这些Handler,我们就几乎可以实现HTTP中的请求中所有的功能。首先介绍一下urllib.request模块里的BaseHandler类,这是其他所有handler类的父类,它提供了最基本的方法,例如default_open,protocol_request等。
会有很多的handler类继承BaseHandler类,下面介绍几个子类:
1.HTTPDefaultErrorHandler用于处理HTTP响应错误,所有错误都会抛出HTTPError类型的错误。
2.HTTPRedirectHandler用于处理重定向。
3.HTTPCookieProcessor用于处理Cookie。
4.ProxyHandler用于设置代理。
5.HTTPPasswordMgr用于管理密码,他维护着用户名密码的对照表。
6.HTTPBasicAuthHandler用于管理认证,如果一个链接打开需要认证,就用这个。
对于这些类的介绍,后面我们会逐一的用实例来解释,这里就先不介绍。当然,除了上面的类,还有一个很重要的类,OpenerDirector类,简称opener类,前面我们用到的urlopen方法实际上就是urllib库为我们提供的一个Opener。
下面我们举几个例子来认识一下opener类和handler类。
这里给出一个网站:https://ssr3.scrape.center,会弹出这样的窗口:
from urllib.request import HTTPPasswordMgrWithDefaultRealm,HTTPBasicAuthHandler,build_opener
from urllib.error import URLError
username='123456'
password='123456'
url='https://login1.scrape.center/'
p=HTTPPasswordMgrWithDefaultRealm()
p.add_password(None,url,username,password)
auth_handler=HTTPBasicAuthHandler(p) #实例化对象
opener=build_opener(auth_handler) #创建opener
try:
result=opener.open(url)
html=result.read().decode('utf-8')
print(html)
except URLError as e:
print(e.reason)
2.代理
我们在做爬虫的时候,难免会用到的代理。如果要使用代理,可以这样做:
from urllib.error import URLError
from urllib.request import ProxyHandler,build_opener
proxy_handler=ProxyHandler({
'http':'http://127.0.0.1:8080',
'https':'http://127.0.0.1:8080'
})
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)
上面使用了ProxyHandler,其参数是一个字典,键名是协议(例如HTTP或HTTPS),键值是代理链接,可以添加多个代理。
然后利用build_opener创建一个类opener,然后发送请求。
后买还有Cookie处理,设计的内容很多,不详细介绍,后面遇到了会直接通过案例来进行讲解。
3.处理异常
我们在进行爬虫操作的时候,难免会出现很多的错误,尤其是使用request类进行操作的时候,这个时候,利用针对request类的urlerror错误类,便可以降低我们的工作量,进行错误抛出,也可以使程序更合理化。
①URLError
URLError类来自urllib库的error模块,继承自OSError类,是error类的基类。它具有一个reason属性,可以返回错误原因。
from urllib.error import URLError
from urllib.request import urlopen
url='https://111.com/404'
try:
response=urlopen(url)
print(response.read().decode('utf-8'))
except URLError as e:
print(e.reason)
程序没有报错,而是直接输出错误原因:
Internal Server Error。
②HTTPError
HTTPError是URLError的子类,专门用来处理HTTP请求错误,例如认证失败等。它有以下几个属性:
1.code:返回HTTP状态码,例如404表示页面不存在。500表示服务器内部错误等。
2.reason:同父类一样,用于返回错误的原因。
3.headers:返回请求头。
from urllib.error import HTTPError
from urllib.request import urlopen
url='http://111.com/404' #这是个错误的网址
try:
response=urlopen(url)
print(response.read().decode('utf-8'))
except HTTPError as e:
print(e.code,e.reason,e.headers)
500 Internal Server Error Server: openresty Date: Thu, 02 Feb 2023 08:02:53 GMT Content-Type: text/html Content-Length: 174 Connection: close
requests的使用
前面虽然我们使用了urllib库进行了爬虫的基本的代码。在写Cookie处理和登陆验证的时候需要用到Handler类和Opener类,而且在写POST,PUT等请求时也会非常复杂。
由于requests库不是python的内置库,需要先下载,使用pip就可以:
pip install requests -i Simple Index
实例的使用:
urllib库中的urlopen请求网页实际上是以GET方法。现在我们来看requests中的get方法。
import requests
r=requests.get('https://www.baidu.com')
print(type(r))
print(r.status_code)
print(type(r.text))
print(r.text[:100])
print(r.cookies)
使用get方法还不算requests的亮眼操作,它还可以很简单的使用post,put等发送请求方法:
import requests
url='https://www.baidu.com'
r=requests.post(url)
r=requests.put(url)
r=requests.delete(url)
r=requests.patch(url)
这里使用requests类确实实现了很大的方便,但是,这只是他强大功能的冰山一角。
GET请求:
get请求我们在上面已经介绍,这里主要是介绍网页抓取,二进制数据保存,等内容。
我们抓取网页的时候,得到的是HTML文件,包含了很多的子页面,如果我们要获取某个子页面的网址,那么我们怎么获取?下面给一个例子:
import requests
import re
r=requests.get('https://ssr1.scrape.center/')
pattern=re.compile('<h2.*?>(.*?)</h2>',re.S)
titles=re.findall(pattern,r.text)
print(titles)
['霸王别姬 - Farewell My Concubine', '这个杀手不太冷 - Léon', '肖申克的救赎 - The Shawshank Redemption', '泰坦尼克号 - Titanic', '罗马假日 - Roman Holiday', '唐伯虎点秋香 - Flirting Scholar', '乱世佳人 - Gone with the Wind', '喜剧之王 - The King of Comedy', '楚门的世界 - The Truman Show', '狮子王 - The Lion King']
这里使用了正则表达式,这里只是当作示例,后面会想详细介绍。
抓取二进制数据:
我们先来看一个案例:
import requests
r=requests.get('https://scrape.center/favicon.ico')
print(r.text)
print(r.content)
第一个出现了乱码,第二个是二进制。由于图片是二进制保存,所以必须用二进制展现,即content属性。想要验证这个问题,我们就将其保存下来:
import requests
r=requests.get('https://scrape.center/favicon.ico')
with open('./favicon.ico','wb') as f:
f.write(r.content)
post请求和get请求相似,用法等基本无差异,所以这里不做过多介绍。
身份认证
在访问简单的身份验证的时候,我们用requests类中的相关函数也可以实现身份验证:
import requests
from requests.auth import HTTPBasicAuth
r=requests.get('https://ssr3.scrape.center/',auth=HTTPBasicAuth('123456','123456'))
print(r.status_code)
此外,除了此种认证方式,requests还有其他认证方式,OAuth认证, 不过此时需要安装oauth包,安装命令如下:
pip install requests_oauthlib
源代码:
#OAuth认证
import requests
from requests_oauthlib import OAuth1
url='https://ssr3.scrape.center/'
oauth=OAuth1('YOUR_APP_KEY','YOUR_APP_SECRET',
'USER_OAUTH_TOKEN','USER_OAUTH_TOKEN_SECRET')
requests.get(url,auth=oauth)
代理设置
import requests
proxy_handler=ProxyHandler({
'http':'http://127.0.0.1:8080',
'https':'http://127.0.0.1:8080'
})
requests.get('https://www.baidu.com',proxies=proxy_handler)
除了基本的HTTP协议代理,也可以使用SOCKS协议代理。
需要先安装socks库。
pip install "requests[socks]"
然后就可以使用SOCKS协议代理了,示例如下:
import requests
proxy_handler=ProxyHandler({
'http':'socks5://user:password@host:port'
})
requests.get('https://www.baidu.com',proxies=proxy_handler)
总结
本节的相关的库已经介绍完毕,其中requests库十分重要,需要好好掌握,由于细节很多,博主这里可能会有遗漏,有些知识博主认为不重要的就省略了,只介绍了重要的和常用的,后面遇到了,会具体分析。
感谢各位小伙伴在在百忙之中花一点时间观看。