随着万维网的迅速发展,加上大数据的出现,快速提取并利用大量的有效数据信息成了焦点,网络爬虫也应运而生。网络爬虫是一种按照一定的规则,自动地抓取万维网信息的程序或者脚本(这是百度百科对爬虫的解释)。
通用网络爬虫:又叫全网爬虫,爬行对象从一些种子 URL 扩充到整个 Web,主要为门户站点搜索引擎和大型 Web 服务提供商采集数据。简而言之就是,爬取一个网站所有信息,通用网络爬虫适用于为搜索引擎搜索广泛的主题,有较强的应用价值。
聚焦网络爬虫:又称主题网络爬虫,指选择性地爬行那些与预先定义好的主题相关页面的网络爬虫,意思就是说爬取用户想要的数据。
增量式网络爬虫:是指对已下载网页采取增量式更新和只爬行新产生的或者已经发生变化网页的爬虫,它能够在一定程度上保证所爬行的页面是尽可能新的页面,就是在已经爬取的数据上再爬取网页更新后的数据,而保持原来的数据不变。
深层网络爬虫:是爬取那些大部分内容不能通过静态链接获取的、隐藏在搜索表单后的,只有用户提交一些关键词才能获得的 Web 页面,比如:暗网,隐藏的登陆表单等等。
a.选取需要爬取的URL(可以理解为网站链接)
b.将URL放入待抓取的URL队列上
c.从待抓取URL队列中读取带抓取队列的URL,解析DNS,并得到主机IP,下载对应网页存储到已下载的网页库中
d.在从下载好的网页数据中分析出其他URL,然后对比已下载的URL去重,进入下一个循环
requsts库一般用在Python的爬虫技术中,这个库是用于构建HTTP请求与解析响应的HTTP库,是由urllib库发展而来,由于requsts库使用方便,导致urllib库一般用在学习Python爬虫基础上,而真正爬取数据所用到的库是requsts库。
requsts库是第三方开源库,需要额外安装,才能使用,源码在GitHub上。
关于库/模块的介绍可以看这篇博文:链接在此
安装requsts库
#在命令解释器上输入
pip install requsts
#注意:这是针对Windows系统的
requests库有7个主要方式,返回Response对象类型
请求方式 | 说明 |
---|---|
requsts.requst(method,url,**kwargs) | 构造一个请求,最基本的方法,用的比较多 |
requsts.get(url,params=None,**kwargs) | 获取网页,对应HTTP中的GET方法,用的比较多 |
requsts.post(url,data=None,json=None,**kwargs) | 向网页提交信息,对应HTTP中的POST方法,用的比较多 |
requsts.head(url,**kwargs) | 获取html网页的头信息,对应HTTP中的HEAD方法 |
requsts.put(url,data=None,**kwargs) | 向html提交put方法,当数据存在时更新数据,当数据不存在是创建数据,对应HTTP中的PUT方法 |
requsts.options(url, **kwargs) | 获取服务器对于某些接口等资源的支持情况的,对应HTTP中的OPTIONS方法 |
requsts.patch(url,data=None,**kwargs) | 向html网页提交局部请求修改的的请求,更新数据,对应HTTP中的PATCH方法 |
requsts.delete(url,**kwargs) | 向html提交删除请求,对应HTTP中的DELETE方法 |
以上方法中,GET
,HEAD
,OPTIONS
是从服务器获取信息到本地,PUT
,POST
,PATCH
,DELETE
是从本地向服务器提交信息。
method是请求方式,对应get/put/post/options/head/patch/delete等7种方法
url是获取html的网页的url
params是url后面添加参数,字典/字节流格式,可选
json是JSON格式的数据,作为Request的内容
data是字典/字节序列/文件对象,作为Request的内容
kwargs是控制访问的参数,有些请求没有个别参数,根据不同请求方式确定,其实七种方法都是调用了requsts.requst方法,所以我们只需要了解requsts.requst的参数即可。
kwargs有以下控制访问的参数
params:字典/字节序列类型,在URL后面添加参数
import requests
params={'a':'one','b':'two'}
url=requests.request('put','http://httpbin.org/put',params=params)
print(url.text)#http://httpbin.org/put?a=one&b=two
#url.url表示实际请求的url
data:字符串类型,作为Request的内容
import requests
data="shuju"
url=requests.request('put','http://httpbin.org/put',data=data)
print(url.text)#在返回结果的data中有"data": "shuju"
json:JSON数据类型,作为Request的内容
import requests
json={'key1':'1', 'key2':'2'}
url=requests.request('put','http://httpbin.org/put',json=json)
print(url.text)#在返回结果的json中有"json":{"key1": "1","key2":"2"}
headers:字典类型,就是HTTP请求头,为了隐藏爬虫信息,模拟浏览器的头部信息
import requests
headers = {"User-Agent":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"}
url=requests.request('put', 'http://httpbin.org/put', headers=headers)
print(url.text)#在返回结果的User-Agent中有"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36"
cookies:字典/CooKiJar,Request中的cookie
import requests
cookies={'mycookies':'working'}
url=requests.request('get','http://httpbin.org/cookies',cookies = cookies)
print(url.text)#在返回结果的"cookies"中有"cookies": {"mycookies": "working"}
auth:元组类型,HTTP认证功能
import requests
url=requests.get('http://httpbin.org/auth',auth=requests.auth.HTTPBasicAuth('user', '123'))
print(url.status_code)
#url.status_code表示状态码
files:字典类型,向网站发送图片、文档等
import requests
fs = {file:open('data.txt','rb')}
url = requests.request('POST','http://httpbin.org/post',files=fs)
timeout:设定超时时间,秒为单位
import requests
#设置必须在1000ms内收到响应,不然抛出异常
url=requests.request('get','http://www.baidu.com/get',timeout=1)
print(url.status_code)
proxies:字典类型,设定访问代理服务器,可以增加登录认证
import requests
#普通代理
proxies_1={"http":"http://127.0.0.1:1080"}#格式是"协议":"代理地址:端口"
#带有用户名和密码的代理
proxies_2={"http":"http://user:[email protected]:9743/"}#格式是"协议":"用户名:密码@代理地址:端口"
#设置socks代理
proxies_3={'http':'socks5://127.0.0.1:1080'}#格式是"协议":"socks5://代理地址:端口"
url=requests.request('get',"https://www.google.com",proxies=proxies_1)
print(url.status_code)
allow_redirects:True/False,默认为True,重定向开关
import requests
url=requests.request('GET','http://httpbin.org/get',allow_redirects=False)
stream: True/False,默认为True,获取内容立即下载开关
import requests
url=requests.request('GET','http://httpbin.org/get/**.txt',stream=False)
verity: True/False默认Ture,用于认证SSL证书开关,如果关闭验证,仍然会报出证书警告
import requests
requests.packages.urllib3.disable_warnings()#关闭警告,如果没有就会出现警告
url = requests.get('https://www.12306.cn',verify=False)
print(url.status_code)#200
cert: 设置本地SSL证书路径
import requests
cert=('/home/youdi/Download/**.crt', '/hone/youdi/.ssh/**.key')
url=requests.request('get','https://www.12306.cn',cert=cert)
print(url.status_code)
到这里后,可以直接跳到第九个标题,中间的博文了解即可。
异常 | 说明 |
---|---|
requests.ConnectTimeout | 连接远程服务器超时异常 |
requests.ConnectionError | 网络连接异常,如DNS查询失败,拒绝连接等 |
requests.DependencyWarning | 尝试导入缺少可选依赖项的模块时发出警告。 |
requests.FileModeWarning | 文件以文本模式打开,但是请求决定了它的二进制长度 |
requests.HTTPError | HTTP错误异常 |
requests.NullHandler | 如果库的用户未配置日志记录,则可能会产生一次性警告 |
requests.ReadTimeout | 服务器没有在分配的时间内发送任何数据 |
requests.RequestException | 处理您的请求时出现不明确的异常。 |
requests.RequestsDependencyWarning | 导入的依赖项与预期的版本范围不匹配 |
requests.Timeout | 请求URL超时,产生超时异常 |
requests.TooManyRedirects | 超过最大重定向次数,产生重定向异常 |
requests.URLRequired | URL缺失异常 |
在requsts库中用dir
函数显示出有这些库类,由于不是很了解,所以就不做说明了,等以后有空在详细介绍。
codes
在requsts库中用dir
函数显示出有这些模块,由于不是很了解,所以就不做说明了,等以后有空在详细介绍。
adapters、api、auth、certs、compat、cookies、exceptions、hooks、models、packages、sessions、status_codes、structures、utils、warnings
在requsts库中用dir
函数显示出有这些库,由于不是很了解,所以就不做说明了,等以后有空在详细介绍。
chardet、logging、urllib3
在requsts库中用dir
函数显示出有这些函数
函数 | 说明 |
---|---|
check_compatibility | 检查版本兼容性 |
session | 使用session对象登录某个网站,再次使用该对象请求该网站的其他网页都会默认使用该session之前使用的cookie等参数 |
对象 | 说明 |
---|---|
PreparedRequest | 针对get/post/put/patch/delete请求提供的参数进行加工处理,以确保目标服务器能正常识别这些数据 |
Response | 一个数据集合体,这个对象可以说是requsts库的核心对象,就是上面请求方式返回的对象,但是要注意的是虽然是同类型对象,但是存在的方法不同,比较重要后面会详细介绍 |
Request | 这个对象把浏览器访问请求的许多东西都结合在一起,为我们后续工作节省了许多步骤 |
Session | 维护一个cookie集合,保留你所有请求痕迹的对象,一个线程安全的连接池,通过这种方式可以让你无间断地进行数据交互,不用每次请求都需要单独认证 |
我们这里说的Response对象是使用了请求方式后,返回的对象,不是单纯的Response对象。
在爬虫里面我们几乎都会使用到这个对象,它是服务器对http请求的响应并返回,然后我们可以对其返回数据进行自定义的操作。
a、apparent_encoding属性
apparent_encoding
属性是从网页的内容中分析网页编码的方式,并且返回的是str
数据类型,但是需要注意的是,这有些消耗计算资源。
#例子
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.apparent_encoding)#utf-8
b、close函数
close
函数是关闭连接,去除内存,可以防止内存溢出,一般不用。
#例子
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
r.close()
c、content属性
content
属性是将爬取的网页内容以二进制的存储,并返回byte
类型,一般用这种类型下载图片或者视频。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.content)#b'二进制形式网页内容'
d、cookies属性
cookies
属性是网页的cookie值,返回一个requests.cookies.RequestsCookieJar对象。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.cookies)
e、elapsed属性
elapsed
属性是从发送请求到响应到达之间经过的时间,返回一个datetime.timedelta对象。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.elapsed)#0:00:00.608318
f、encoding属性
encoding
属性是一个属性,与上面的apparent_encoding
一样,但是是从http
中的header
中的charset
字段中提取的编码方式,并且返回的是str
数据类型,它决定了text
属性的编码,若header
中没有charset
字段则默认为ISO-8859-1
编码模式,则无法解析中文,这是乱码的原因。
当乱码时可以使用apparent_encoding赋值给encoding
#例子
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.encoding)#UTF-8
g、headers属性
headers
属性与前面kwargs
的参数中的headers
是一样的,就是HTTP请求头,为了隐藏爬虫信息,模拟浏览器的头部信息,以字典的形式存储,可单独取出某个字段的值,返回一个requests.structures.CaseInsensitiveDict
对象。
#例子
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.headers)#{'Server': 'openresty', xxxxxxxxxxx}
h、history属性
history
属性是追踪重定向,为了完成请求而创建,按照从最老到最近的请求进行排序,与前面kwargs
的参数中的allow_redirects
搭配使用,返回一个list
数据类型。
r = requests.get("http://github.com")
print(r.history)#[]
i、is_permanent_redirect属性
is_permanent_redirect
属性是判断是否永久重定向,True
(是)和False
(否),返回一个bool
类型。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.is_permanent_redirect)#False
j、is_redirect属性
is_redirect
属性是判断是否重定向,True
(是)和False
(否),返回一个list
类型。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.is_redirect)#False
k、iter_content函数
iter_content(chunk_size=1, decode_unicode=False)
函数是为了避免下载内容过大占用大量内存而使用的函数,在响应数据上迭代,返回generator
类型。
chunk_size
必须为int
或None
类型,是应该读入内存的字节数。根据stream
的值,None
的值将有不同的功能,stream
值为True
将在数据到达时读取数据,无论数据块大小是多少。如果stream
值为False
,数据将作为单个块返回。
decode_unicode
为True
,则将使用基于响应的最佳可用编码对内容进行解码。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
File = open('H:\\1\\csdn.txt', 'wb')
for data in r.iter_content(100):
File.write(data)
print(data)
#b'\n\n
l、iter_lines函数
iter_lines(chunk_size=512, decode_unicode=False, delimiter=None)
函数与iter_content
函数一样为了避免下载内容过大占用大量内存而使用的函数,但是每次只迭代一行数据,多次调用该方法会导致部分收到的数据丢失,返回generator
类型。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
File = open('H:\\1\\csdn.txt', 'wb')
for data in r.iter_lines():
File.write(data)
print(data)
n、json
json
是用于将响应解析成json格式,如果响应数据里面有字典类型的话,否则,抛出异常,返回一个dict
类型。
import requests
url=requests.request('put','http://httpbin.org/put')
print(url.json())
m、links属性
links
属性是响应的解析头链接,返回一个dict
类型。许多HTTP API都有响应头链接字段的特性,使得 API 能够更好地自我描述和自我显露,例如:GitHub 在 API 中为分页使用这些特性。(自己也不是太懂这玩意,是网上的代码)
url = 'https://api.github.com/users/kennethreitz/repos?page=1&per_page=10'
r = requests.head(url=url)
r.headers['link']
print(r.links["next"])#{'url': 'https://api.github.com/users/kennethreitz/repos?page=2&per_page=10', 'rel': 'next'}
o、next
next
是返回重定向链中下一个请求的PreparedRequest对象,如果有的话。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.next)
p、ok属性
ok
属性是检查status_code
的值是否小于400,True
(是)和False
(否),返回一个bool
类型。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.ok)#True
q、raise_for_status函数
raise_for_status
函数是抛出异常。说实话这个真不知道干嘛的。zzzzz
import requests
r = requests.get("https://blog.csdn.net/")
print(r.raise_for_status())
r、raw
raw
是获取来自服务器的原始套接字响应,表示urllib3.response.HTTPResponse对象。使用raw时,要求在请求时设置stream=True
。(自己也不是太懂这玩意,个人感觉应该是服务器发来的没有被解析的数据,以下是网上的代码)
import requests
r = requests.post("https://blog.csdn.net/qq_4173424",stream=True)
print(r.raw.read(10))
s、reason属性
reason
属性是对响应状态的描述,即Not Found
orOK
,感觉通过ok
属性或者status_code
属性也可以判断,返回一个str
类型。
import requests
r = requests.post("https://blog.csdn.net/qq_41734243")
print(r.reason)#OK
t、request属性
request
属性是可以用于查看发送请求时的信息,可以在后面添加一些参数,如:r.request.headers就是查看请求头,返回一个PreparedRequest
对象。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.request)#
u、status_code属性
status_code
属性是http状态码,并返回int
类型。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.status_code)#200
v、text属性
text
属性是将爬取的网页内容以encoding
内的编码格式为编码存储的字符串,并返回str
类型。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.text)#xxxxxx
w、url属性
url
属性是存储最终访问网站的URL,返回str
类型。
import requests
r = requests.get("https://blog.csdn.net/qq_41734243")
print(r.url)
这里介绍几个知识点:
1、re库是python正则表达式所用到的库,这里有正则表达式的介绍:链接
2、fake_useragent库可以用来虚拟请求头,就是User-Agent
3、open函数就是通常说的IO流操作,这里有open函数的介绍:链接
4、try:…except:…语句是捕抓异常,这里有捕抓异常的介绍:链接
5、os模块是管理的系统模块
import requests #http请求库
import re #正则表达式
import fake_useragent#虚拟请求头,即User-Agent
import os #系统模块
#获取网页
#get_url函数是用来获取网页响应的,并返Response
def get_url(url, headers, timeout = 7):
#获取网页
r = requests.get(url=url, headers=headers, timeout = timeout)
# 修改编码
r.encoding = r.apparent_encoding
return r
#对响应的文件操作
def text_url(r, headers):
#利用正则表达式筛选图片网页
url_list = re.findall(r'"objURL":"(http.*?)"', r.text)
#图片数量计数
count = 1
#os.getcwd()函数是显示当前目录
print("图片在目录下哦!路径是:{}".format(os.getcwd()))
#利用open函数进行文件操作
for i in url_list:
try:
img = get_url(i, headers)
#利用open函数下载图片到当前目录下,os.sep()函数是系统分隔符
with open(r"{}{}html{}.jpg".format(os.getcwd(), os.sep, count), 'wb') as f:
f.write(img.content)
print("下载第{}张成功!".format(count))
except Exception as e:
print('下载第{}张失败!抓取源代码失败:{}'.format(count, e))
count += 1
print("下载完成结束!共有{}张!路径在{}下".format(count, os.getcwd()))
#main函数
def main():
name = input("请输入需要下载的图片名称:")
url = "http://image.baidu.com/search/index?tn=baiduimage&word={}".format(name)
#调用fake_useragent虚拟请求头User-Agent
headers = {"User-Agent":fake_useragent.UserAgent().random}
#print(headers)
#调用get_url函数获取网页数据
try:
text = get_url(url, headers)
# 处理网页数据
text_url(text, headers)
except Exception as e:
print('抓取源代码失败:{}'.format(e))
#程序开头
if __name__ == "__main__":
main()
以上是request库介绍及爬取百度图片的脚本,如有发现博文有什么问题或者对博文有什么疑惑,可以私信我!
注意:本文章仅供学习和参考!非法的爬虫技术已经属于违法!!!