Python网络爬虫应用一般分为两部:
(1)通过网络连接获取网页内容
(2)对获得的网页内容进行处理
- 这两个步骤分别使用不同的函数库:requests 和beautifulsoup4
1.Robots排除协议
Robots 排除协议(Robots Exclusion Protocol),也被称为爬虫协议,它是网站管理者表达是否希望爬虫自动获取网络信息意愿的方法。管理者可以在网站根目录放置一个robots.txt 文件,并在文件中列出哪些链接不允许爬虫爬取。一般搜索引擎的爬虫会首先捕获这个文件,并根据文件要求爬取网站内容。Robots 排除协议重点约定不希望爬虫获取的内容,如果没有该文件则表示网站内容可以被爬虫获得,然而,Robots 协议不是命令和强制手段,只是国际互联网的一种通用道德规范。绝大部分成熟的搜索引擎爬虫都会遵循这个协议,建议个人也能按照互联网规范要求合理使用爬虫技术。
2.request库的使用
request 库支持非常丰富的链接访问功能,包括:国际域名和URL 获取、HTTP 长连接和连接缓存、HTTP 会话和Cookie 保持、浏览器使用风格的SSL 验证、基本的摘要认证、有效的键值对Cookie 记录、自动解压缩、自动内容解码、文件分块上传、HTTP(S)代理功能、连接超时处理、流数据下载等。
有关requests库的更多介绍可看:
Requests: HTTP for Humans™ — Requests 2.31.0 documentation
(1)安装request库
pip install requests 或 pip3 install requests
** (2)request库中的请求函数**
函数描述get(url[,timeout=n])对应于HTTP的GET****方式,获取网页最常用的方法,可以增加timeout=n参数,设定每次请求超时时间为n秒post(url,data={‘key’:’value’})对应于HTTP的POST方式,其中字典用于传递客户数据delete(url)向网页提交删除请求head(url)获取html网页头信息options(url)对应于HTTP的OPTIONs方式put(url, data={‘key’:’value’})向网页提交put请求,其中字典用于传递客户数据
(3)get的用法
get()是获取网页最常用的方式,在调用requests.get()函数后,返回的网页内容会保存为一个Response 对象,其中,get()函数的参数url必须采用HTTP 或HTTPS方式访问
>>> import requests
>>> r = requests.get('http://www.baidu.com')#使用get方法打开链接
>>> type(r)
requests.models.Response #返回Response对象
(4)response对象的属性
•和浏览器的交互过程一样,requests.get()代表请求过程,它返回的Response 对象代表响应,Response 对象的属性如下表所示,需要采用.形式使用。
•status_code 属性返回请求HTTP 后的状态,在处理数据之前要先判断状态情况,如果请求未被响应,需要终止内容处理。
•text 属性是请求的页面内容,以字符串形式展示。
•encoding 属性非常重要,它给出了返回页面内容的编码方式,可以通过对encoding 属性赋值更改编码方式,以便于处理中文字符。
•content 属性是页面内容的二进制形式。
•json()方法能够在HTTP 响应内容中解析存在的JSON 数据,这将带来解析HTTP的便利。
•raise_for_status()方法能在非成功响应后产生异常,即只要返回的请求状态status_code 不是200,这个方法会产生一个异常,用于try…except 语句。只需要在收到响应调用这个方法,就可以避开状态字200 以外的各种意外情况。
表格总结如下:
函数描述status_codeHTTP请求的返回状态,整数,200表示连接成功,404表示失败textHTTP响应内容的字符串形式,即,也是url对应的页面内容encodingHTTP响应内容的编码方式content
HTTP响应内容的二进制形式
json()如果HTTP响应内容包含JSON格式数据,该方法解析JSON数据
raise_for_status()
如果不是200,那么这个方法就会产出异常
示例:
>>> import requests
>>> r = requests.get('http://www.baidu.com')
>>> r.status_code #返回状态
200
>>> r.text #观察返回的内容,中文字符能否正常显示
(输出略)
>>> r.encoding
'ISO-8859-1'
>>> r.encoding = 'utf-8' #更改编码方式为utf-8
>>> r.text #更改完成,返回内容中的中文字符可以正常显示
(输出略)
(5)requests产生的异常
•当遇到网络问题时,如:DNS 查询失败、拒绝连接等,requests 会抛出**ConnectionError **异常;
•遇到无效HTTP 响应时,requests 则会抛出**HTTPError **异常;
•若请求url 超时,则抛出Timeout 异常;若请求超过了设定的最大重定向次数,则会抛出一个**TooManyRedirects **异常。
(6)获取一个网页内容
import requests
def getHTMLText(url):
try: r=request.get(url,timeout=30) r.raise_for_status() #如果状态不是200,引发异常 r.encoding='utf-8' return r.text except: return ""
url = "http://www.baidu.com"
print(getHTMLText(url))
HTTP的GET和POST
HTTP 协议定义了客户端与服务器交互的不同方法,最基本的方法是GET 和POST。顾名思义,GET 可以根据某链接获得内容,POST 用于发送内容。然而,GET 也可以向链接提交内容。
注:使用** get() 方法访问百度页面时,可以通过 text 属性和 content 属性来获取网页的内容**。这两种方法返回的内容长度可能会有所不同,原因如下:
text 属性返回的是经过解码后的字符串内容,通常是按照页面的字符编码(比如 UTF-8)进行解析的网页文本内容。因此,len() 函数返回的是网页文本的字符数。
content 属性返回的是未经解码的字节内容,即网页的原始字节数据。因此,len() 函数返回的是网页内容的字节数。
由于中文字符通常需要多个字节来表示,因此在使用 len() 函数计算时,text 属性返回的长度通常会大于 content 属性返回的长度。这就是长度差异产生的主要原因。
3.beautifulsoup4库的使用
使用requests 库获取HTML 页面并将其转换成字符串后,需要进一步解析HTML页面格式,提取有用信息,这需要处理HTML 和XML 的函数库。beautifulsoup4 库,也称为Beautiful Soup 库或bs4 库,用于解析和处理HTML和XML。
需要注意,它不是**BeautifulSoup **库。它的最大优点是能根据HTML 和XML 语法建立解析树,进而高效解析其中的内容。
HTML 建立的Web 页面一般非常复杂,除了有用的内容信息外,还包括大量用于页面格式的元素,直接解析一个Web 网页需要深入了解HTML 语法,而且比较复杂。beautifulsoup4 库将专业的Web 页面格式解析部分封装成函数,提供了若干有用且便捷的处理函数。
(1)beautifulsoup4的安装
pip install beautifulsoup4 或 pip3 install beautifulsoup4
(2)beautifulsoup4的应用
beautifulsoup4 库采用面向对象思想实现,简单说,它把每个页面当做一个对象,通过.的方式调用对象的属性(即包含的内容),或者通过.()的方式调用方法(即处理函数)。
在使用beautifulsoup4 库之前,需要进行引用,由于这个库的名字非常特殊且采用面向对象方式组织,可以用from…import 方式从库中直接引用BeautifulSoup 类,方法如下:
from bs4 import BeautifulSoup
有关beautifulsoup4库的使用可以看:
Beautiful Soup: We called him Tortoise because he taught us.
•beautifulsoup4 库中最主要的是BeautifulSoup 类,每个实例化的对象相当于一个页面。采用from…import 导入库中类后,使用BeautifulSoup()创建一个BeautifulSoup对象。
>>> import requests
>>> from bs4 import BeautifulSoup
>>> r = requests.get('http://www.baidu.com')
>>> r.encoding = 'utf-8'
>>> soup = BeautifulSoup(r.text)
>>> print(type(soup))
<class 'bs4.BeautifulSoup'>
•创建的BeautifulSoup 对象是一个树形结构,它包含HTML 页面里的每一个Tag(标签)元素,如<head>、<body>等。具体来说,HTML 中的主要结构都变成了BeautifulSoup 对象的一个属性,可以直接用.形式获得,其中的名字采用HTML 中标签的名字。
•beautifulsoup对象常用属性:
属性描述headHTML页面的<head>内容titleHTML页面标题,在<head>之中,由<title>标记bodyHTML页面的<body>内容pHTML页面中第一个
内容stringsHTML页面所有呈现在web上的字符串,即标签的内容,可迭代stripped_stringsHTML页面所有呈现在web上的非空字符串(自动去掉空白字符串),可迭代
示例:
>>> import requests
>>> from bs4 import BeautifulSoup
>>> r = requests.get('http://www.baidu.com')
>>> r.encoding = 'utf-8'
>>> soup = BeautifulSoup(r.text)
>>> soup.head
<head><meta content="text/html;charset=utf-8" (省略...)
>>> title = soup.title
<title>百度一下,你就知道</title>
>>> type(title)
bs4.element.Tag
>>> soup.p
<p id="lh"> <a href="http://home.baidu.com">关于百度</a>
<a href="http://ir.baidu.com">About Baidu</a> </p>
•Tag标签
每一个Tag 标签在beautifulsoup4 库中也是一个对象,称为Tag 对象。上例中,title 是一个标签对象。每个标签对象在HTML 中都有以下类似的结构:
其中,尖括号(<>)中的标签的名字是name,尖括号内其他项是attrs,尖括号之间的内容是string。因此,可以通过Tag 对象的name、attrs 和string 属性获得相应内容,采用.的语法形式。
Tag有4个常用属性:
属性描述name 字符串,标签的名字,比如divattrs字典,包含了原来页面Tag所有的属性,比如hrefcontents列表,这个Tag下所有子Tag的内容string字符串,Tag所包围的文本,网页中真实的文字
示例:
>>> soup.a
<a class="mnav" href="http://news.baidu.com" name="tj_trnews">新闻</a>
>>> soup.a.attrs
{'href': 'http://news.baidu.com', 'name': 'tj_trnews', 'class': ['mnav']}
>>> soup.a.string
'新闻'
>>> title = soup.title
>>> title.string
'百度一下,你就知道'
>>> soup.p.contents
[' ',
<a href="http://home.baidu.com">关于百度</a>,
' ',
<a href="http://ir.baidu.com">About Baidu</a>,
' ']
注:
由于HTML 语法可以在标签中嵌套其他标签,所以,string 属性的返回值遵循如下原则:
•如果标签内部没有其他标签,string 属性返回其中的内容;
•如果标签内部有其他标签,但只有一个标签,string 属性返回最里面标签的内容;
•如果标签内部有超过1 层嵌套的标签,string 属性返回None(空字符串)。
•HTML 语法中同一个标签会有很多内容,例如标签,百度首页一共有54 处,直接调用soup.a 只能返回第一个。
查找对应标签
•当需要列出标签对应的所有内容或者需要找到非第一个标签时,需要用到BeautifulSoup 的find()和find_all()方法。这两个方法会遍历整个HTML 文档,按照条件返回标签内容。
find_all()属性:
属性描述BeautifulSoup.find_all(name, attrs, recursive, string, limit)根据参数找到对应标签,返回列表类型。name: 按照Tag标签名字检索,名字用字符串形式表示,例如:dvi, li;attrs: 按照Tag标签属性值检索,需要列出属性名称和值,采用JSON表示;recursive: 设置查找层次,只查找当前标签下一层时使用recursive=Falsestring:按照关键字检索string属性内容,采用string=开始;limit:返回结果的个数,默认返回全部结果
>>> a = soup.find_all('a') #查找所有的标签a
>>> len(a) #本页标签<a>的数量
54
>>> soup.find_all('script') #查找所有标签script
[<script>
(function(){
var hashMatch=document.location...(省略)
>>> soup.find_all('script',{'src':"https://pss.bdstatic.com/static/
superman/js/components/hotsearch-5af0f864cf.js"}) #筛选,只查找src=字符串的标签
[<script src="https://pss.bdstatic.com/static/superman/js/
components/hotsearch-5af0f864cf.js"></script>]'百度一下,你就知道'
>>> import re #使用正则表达式库,可用这个库实现字符串片段匹配
>>> soup.find_all('script',{'src':re.compile('jquery')})
[<script src="https://pss.bdstatic.com/static/superman/js/lib/
jquery-1-edb203c114.10.2.js" type="text/javascript"></script>]
>>> soup.find_all(string=re.compile('百度')) #检索string属性的内容
['百度一下,你就知道', '百度首页', '查看全部百度产品 >',
'关于百度', '使用百度前必读', '百度APP扫码登录', '百度一下\xa0生活更好']
简单说,BeautifulSoup 的find_all()方法可以根据标签名字、标签属性和内容检索并返回标签列表,通过片段字符串检索时需要使用正则表达式re 函数库,re 是Python 标准库,直接通过import re 即可使用。
采用re.compile('jquery')实现对片段字符串(如'jquery')的检索。当对标签属性检索时,属性和对应的值采用JSON格式,例如:
'src':re.compile('jquery')
其中,键值对中值的部分可以是字符串或者正则表达式。
find()属性
除了find_all()方法,BeautifulSoup 类还提供一个find()方法,它们的区别只是前者返回全部结果而后者返回找到的第一个结果,find_all()函数由于可能返回更多结果,所以采用列表形式;find()函数返回字符串形式。
属性描述BeautifulSoup.find(name, attrs, recursive, string)根据参数找到对应标签,返回找到的第一个值,字符串。name: 按照Tag标签名字检索,名字用字符串形式表示,例如:dvi, li;attrs: 按照Tag标签属性值检索,需要列出属性名称和值,采用JSON表示;recursive: 设置查找层次,只查找当前标签下一层时使用recursive=Falsestring:按照关键字检索string属性内容,采用string=开始;
以下是爬虫的示例:
版权归原作者 dulu~dulu 所有, 如有侵权,请联系我们删除。