Python网络爬虫【1】-- Request库、 Robos协议 、BeautifulSoup库 、简单爬虫项目

单元一:Requests库入门-HTTP协议及Requests库方法(SHD)

1、Requests库的7个主要方法

方法说明
requests.request()构造一个请求,支撑一下各个方法的基础方法
requests.get()获取HTML网页的主要方法,对应于HTTP的GET
requests.head()获取HTML网页头信息的方法,对应于HTTP的HEAD
requests.post()向HTML网页提交POST请求的方法,对应于HTTP的POST
requests.put()向HTML网页提交PUT请求的方法,对应于HTTP的PUT
requests.path()向HTML网页提交局部修改请求,对应HTTP的PATCH
requests.delete()向HTML网页提交删除请求,对应HTTP的DELETE

2、HTTP协议

1.HTTP,Hypertext Transfer Protocol,超文本传输协议。

2.HTTP是一个基于“请求与响应”模式的、无状态的应用层协议。

​ 简单说,用户发起请求,服务器做相关相应,这就是请求与响应的模式,无状态指的是第一次请求与第二次请求之间并没有关联性,应用层协议指的是该协议工作在HTTP协议之上。

3.HTTP协议采用URL作为定位网络资源的标识。

​ URL格式: http://host[:port][path]

+ host: 合法的Internet主机域名或者IP地址
+ port: 端口号,缺省端口为80
+ path: 请求资源的路径(资源在主机或者IP地址服务器上所包含的内部路径)

​ HTTP URL的理解:URL是通过HTTP协议存储资源的Internet路径,一个URL对应一个数据资源。

4.HTTP协议对资源的操作

方法说明
GET请求获取URL位置的资源
HEAD请求获取URL位置资源的相应消息报告,即获取该资源的头部信息
POST请求向URL位置的资源后附加新的数据
PUT请求向URL位置存储一个资源,覆盖原URL位置的资源
PATCH请求局部更新URL位置的资源,即改变该处资源的部分内容
DELETE请求删除URL位置存储的资源

在这里插入图片描述

HTTP协议通过URL对资源做定位,通过上面六个常用的方法对资源进行管理。

理解PATCH和PUT区别:

​ 假设URL位置有一组数据UserInfo,包括UserID, UserName等20个字段。

​ 需求:用户修改UserName,其它不变。

  • 采用PATCH,仅向URL提交UserName的局部更新请求。
  • 采用PUT,必须将所有20个字段一并提交到URL,未提交字段被删除。

PATCH的最主要好处:节省网络带宽

HTTP协议方法Requests库方法功能一致性
GETrequests.request()一致
HEADrequests.head()一致
POSTrequests.post()一致
PUTrequests.put()一致
PATCHrequests.patch()一致
DELETErequests.delete()一致

3、 Requests库的使用

request方法的使用(是其它方法的基础)
1)语法
requests.request(method, url, **kwargs)

选项:
method: 请求方式,对应get/put/post/等一共7种
    r = requests.request('GET', url, **kwargs)
    r = requests.request('HEAD', url, **kwargs)
    r = requests.request('POST', url, **kwargs)
    r = requests.request('PUT', url, **kwargs)
    r = requests.request('PATCH', url, **kwargs)
    r = requests.request('DELETE', url, **kwargs)
    r = requests.request('OPTIONS', url, **kwargs)
url:拟获取页面的url链接
**kwargs:控制访问参数,共13个
    params: 字典或字节序列,作为参数增加到url中
    data: 字典、字节序列或文件对象,作为Request的内容
    json: JSON格式的数据,作为Request的内容
    headers: 字典,HTTP定制头
    cookies: 字典或CookieJar, Request中的cookie
    auth: 元组,支持HTTP认证功能
    files: 字典类型,传输文件
    timeout: 设定超时时间,秒为单位
    proxies: 字典类型,设定访问代理服务器,可以增加登陆认证
    all_redirects: True/False, 默认为True,重定向开关
    stream: True/False, 默认为True, 获取内容立即下载开关
    verify: True/False, 默认为True, 认证SSL证书开关
    cert: 本体SSL证书路径

参数parmas:

>>> kv = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.request('GET', 'http://python123.io/ws', params = kv)
>>> r.url
'https://python123.io/ws?key1=value1&key2=value2'

参数data:

>>> kv = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.request('POST', 'http://python123.io/ws', data = kv)
>>> body = 'information'
>>> r = requests.request('POST', 'http://python123.io/ws', data = body) 

参数json:

>>> r = requests.request('POST', 'http://python123.io/ws', json = kv)

参数headers:

>>> hd = {'user-agent': 'Chrome/10'} ## 模拟浏览器Chrome10访问
>>> r = requests.request('POST', 'http://python123.io/ws', headers = hd)

参数files:

>>> fs = {'file': open('data.xls', 'rb')} 
>>> r = requests.request('POST', 'http://python123.io/ws', files = fs)    

参数timeout:

>>> r = requests.request('GET', 'http://python123.io/ws', timeout=10)

参数proxies:

>>> pxs = {'http': 'http://user:pass@10.10.10.1:1234', 'https': 'https://10.10.10.1:4321'}
>>> r = requests.request('GET', 'http://www.baidu.com', proxies = pxs)   
head方法的使用
1)语法
requests.head(url, **kwargs)

选项:
url:拟获取页面的url链接
**kwargs:13个控制访问的参数
2)例子
>>> import requests
>>> r = requests.head('http://www.baidu.com')
>>> r.headers
{'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Mon, 29 Jun 2020 06:22:52 GMT', 'Last-Modified': 'Mon, 13 Jun 2016 02:50:26 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18'}
>>> r.text
''
post方法的使用
1)语法
requests.post(url, data=None, json=NOne, **kwargs)

选项:
url:拟获取页面的url链接
data: 字典、字节序列或文件,Request的内容
json: JSON格式的数据,Request的内容
**kwargs:11个控制访问的参数
2)例子
  • 提交字典类型(或者键值对),其存放在form的字段下
>>> payload = {'key1': 'value1', 'key2': 'value2'} 
>>> r = requests.post('http://httpbin.org/post', data = payload)
>>> print(r.text)
···
  "form": {
    "key1": "value1",
    "key2": "value2"
···
  • 直接提交数据,其存放在data的字段下
>>> r = requests.post('http://httpbin.org/post', data = 'ABC')
>>> print(r.text)
{
"args": {},
"data": "ABC",
"files": {},
···
}
put方法的使用
1)语法
requests.put(url, data=None, **kwargs)

选项:
url: 拟更新页面的url链接
data:字典、字节序列、或文件,Request的内容
**kwargs: 12个控制访问的参数
2)例子
>>> payload = {'key1': 'value1', 'key2': 'value2'}
>>> r = requests.put('http://httpbin.org/put', data = payload)
>>> print(r.text)
{
  "args": {},
  "data": "",
  "files": {},
  "form": {
    "key1": "value1",
    "key2": "value2"
      ...
}
patch方法使用
1)语法
requests.patch(url, data=None, **kwargs)

选项:
url: 拟更新页面的url链接
data:字典、字节序列、或文件,Request的内容
**kwargs: 12个控制访问的参数
get方法的使用
1)语法
requests.get(url, params = None, **kwargs)

选项:
url:拟获取页面的url链接
params:url中的额外参数,字典或字节流格式,可选
**kwargs:12个控制访问的参数(除了parmas)
返回的是一个Respose对象

在这里插入图片描述

>>> import requests
>>> r = requests.get('http://www.baidu.com')
>>> print(r.status_code)
200
>>> type(r)
<class 'requests.models.Response'>
>>> r.headers
{'Cache-Control': 'private, no-cache, no-store, proxy-revalidate, no-transform', 'Connection': 'keep-alive', 'Content-Encoding': 'gzip', 'Content-Type': 'text/html', 'Date': 'Mon, 29 Jun 2020 06:46:43 GMT', 'Last-Modified': 'Mon, 23 Jan 2017 13:27:56 GMT', 'Pragma': 'no-cache', 'Server': 'bfe/1.0.8.18', 'Set-Cookie': 'BDORZ=27315; max-age=86400; domain=.baidu.com; path=/', 'Transfer-Encoding': 'chunked'}
>>>                                 
2)Response对象的属性
属性说明
r.status_codeHTTP请求的返回状态,200表示连接成功,404表示失败
r.textHTTP相应内容的字符串形式,即,url对应的页面内容
r.encoding从HTTP header中猜测的响应内容编码方式
r.apparent_encoding从内容中分析出响应内容编码方式(备用编码方式)
r.contentHTTP响应内容的二进制形式
3)Respose对象处理流程

在这里插入图片描述

4)理解Respose的编码

先看个例子:

>>> import requests
>>> r = requests.get('http://www.baidu.com')
>>> r.status_code
200
>>> r.text
'<!DOCTYPE html>\r\n<!--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=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>ç\x99¾åº¦ä¸\x80ä¸\x8bï¼\x8cä½\xa0å°±ç\x9f¥é\x81\x93</title></head> <body link=#0000cc> <div 
...
>>> r.encoding
'ISO-8859-1'
>>> r.apparent_encoding
'utf-8'
>>> r.encoding = 'utf-8'
>>> r.text
'<!DOCTYPE html>\r\n<!--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=http://s1.bdstatic.com/r/www/cache/bdorz/baidu.min.css><title>百度一下,你就知道</title></head> <body link=#0000cc> 
...
属性说明
r.encoding从HTTP header中猜测的响应内容编码方式
r.apparent_encoding从内容中分析出的响应内容编码方式(备选编码方式)

r.encoding: 如果header中不存在charset,则认为编码为ISO-8859-1。

r.apparent_encoding: 根据网页内容分析出的编码方式。

delete方法的使用
1)语法
requests.delete(url, **kwargs)

选项:
url: 拟删除页面的url链接
**kwargs: 13个控制访问的参数

4、Requests爬取网页的通用代码框架

1)Requests库的异常

异常说明
requests.ConnectionError网络连接错误异常,如DNS查询异常、拒绝连接等
requests.HTTPErrorHTTP错误异常
requests.URLRequiredURL缺失异常
requests.TooManyRedirects超过最大重定向次数,产生重定向异常
requests.ConnectTimeout连接远程服务器超时异常
requests.Timeout请求URL超时,产生超时异常
requests.raise_for_status()如果不是200,产生异常requests.HTTPError

2)通用代码框架

import requests


def getHTMLText(url):
    try:
        r = requests.get(url, timeout=30)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return "产生异常"


if __name__ == '__main__':
    url = 'http://www.baidu.com'
    print(getHTMLText(url))

单元二、Robots协议

1)Robots协议

Robos Exclusion Standard 网络爬虫排除标准

作用:网站告知网络爬虫哪些页面可以抓取,哪些不行

Robots协议基本语法:

在这里插入图片描述

2)Robots协议遵守的方式

Rotots协议的使用:

网络爬虫:自动或人工识别robots.txt,再进行内容爬取

约束性:Rotots协议是建议但非约束性,网络爬虫可以不遵守,但存在法律风险。(面向监狱爬虫, 哈哈)

3)网络爬虫的尺寸

在这里插入图片描述

单元三、 BeautifulSoup库

1)Beautiful Soup库的理解

在这里插入图片描述

Beautiful Soup库是解析、遍历、维护“标签树”的功能库。

Beautiful Soup对应一个HTML/XML文档的全部内容。

2)Beautiful Soup库解析器

解析器使用方法条件
bs4的HTML解析器BeautifulSoup(mk, ‘html.parser’)安装bs4库
lxml的HTML解析器BeautifulSoup(mk, ‘lxml’)pip install lxml
lxml的XML解析器BeautifulSoup(mk, ‘xml’)pip install lxml
html5lib的解析器BeautifulSoup(mk, ‘html5lib’)pip install html5lib

3)Beautiful Soup类的基本元素

基本元素说明
Tag标签,最基本的信息组织单元,分别用<>和</>标明开头和结尾
Name标签的名字,

p>的名字是‘p’,格式:.name
Attributes标签的属性,字典形式组织,格式:.attrs
NavigablesString标签内非属性字符串,<>…</>中字符串,格式:.string
Comment标签内字符串的注释部分,一种特殊的Comment类型

在这里插入图片描述

4)标签树的遍历

1)标签树的下行遍历

属性说明
.contents子节点的列表,将所有儿子节点存入列表,是列表类型
.children子结点的迭代类型,与.contents类似,用于循环遍历儿子节点
.descendants子孙节点的迭代类型,包含所有子孙节点,用于循环遍历

2)标签树的上行遍历

属性说明
.parent节点的父亲标签
.parents节点先辈标签的迭代类型,用于循环遍历先辈节点

3)标签树的平行遍历

属性说明
.next_sibling返回按照HTML文本顺序的下一个平行节点标签
.previous_sibling返回按照HTML文本顺序的上一个平行节点标签
.next_siblings迭代类型,返回按照HTML文本顺序的后续所有平行节点标签
.previous_siblings迭代类型,返回按照HTML文本顺序的前续所有平行节点标签

在这里插入图片描述

4)总结

在这里插入图片描述

5)基于bs4的HTML输出

  • HTML的格式化

    >>> import bs4 import BeautifulSoup
    >>> soup = BeautifulSoup(demo, 'html.parser')
    >>> soup.prettify() ##在标签后面增加'\n' 
    >>> print(soup.prettify()) ## 使用print能更清晰的看出来
    >>> soup.a.prettify()
    

单元四、信息组织与提取方法

1)信息标记的三种方式

XML, JSON, YAML

2)信息提取的一般方法

  • 方法一:完整解析信息的标记形式,再提取关键信息

    XML JSON YAML

    需要标记解析器 例如:bs4库的标记树遍历

    优先:信息解析准确

    缺点:提取过程繁琐,速度慢

  • 方法二:无标记形式,直接搜索关键信息

    搜索

    对信息的文本查找函数即可。

    优点:提取过程简单,速度较快

    缺点:提取结果准确性与信息内容有关

  • 方法三:融合方法:结合形式解析与搜索方法,提取关键信息

    XML JSON YAML 搜索

    需要标记解析器及文本查找函数

实例:提取HTML中所有的URL链接

思路;1)搜索到所有的标签

​ 2)解析标签格式,提取href后的链接内容

3)基于bs4的HTML内容查找方法

<tag>.fint_all(name, attrs, recursive, string, **kwargs)
其等价于<tag>(..)


返回:
一个列表类型,存储查找的结果

选项:
name: 对标签名称的检索字符串
attrs: 对标签属性值的检索字符串,可标注属性索引
recursive: 是否对子孙全部索引,默认True
string: <>...</>中字符串区域的检索字符串
**kwargs: 

参数name:

>>> soup.find_all('a') ## 查找所有a标签
>>> soup.find_all(['a', 'b']) ## 查找所有a, b标签

参数attrs:

>>> soup.find_all('p', 'course')
>>> soup.find(id = 'link1')

参数recursive:

>>> soup.find_all('a', recursive = True)
>>> soup.find_all('a', recursive = False)

参数string:

>>> soup.find_all(string = 'Basic Python')

简写:

(…) 等价于 .find_all(…)

soup(…) 等价于 soup.find_all(…)

拓展方法:

方法说明
<>.find()搜索且只返回一个结果,字符串类型,同.find_all()参数
<>.find_parents()在先辈节点中搜索,返回列表类型,同.find_all()参数
<>.find_parent()在先辈节点中返回一个结果,字符串类型, 同.find_all()参数
<>.find_next_siblings()在后续平行节点中搜索,返回列表类型, 同.find_all()参数
<>.find_next_sibling()在后续平行节点中返回一个结果,字符串类型, 同.find_all()参数
<>.find_previous_siblings()在前续平行节点中搜索,返回列表类型, , 同.find_all()参数
<>.find_previous_sibling()在前续平行节点中返回一个结果,字符串类型, 同.find_all()参数

案例:爬取最好中国大学网

import requests
import bs4
from bs4 import BeautifulSoup


def getHTMLText(url):
    try:
        r = requests.get(url)
        r.raise_for_status()
        r.encoding = r.apparent_encoding
        return r.text
    except:
        return ""


def fillUnivList(ulist, html):
    soup = BeautifulSoup(html, 'html.parser')
    for tr in soup.find('tbody').children:
        if isinstance(tr, bs4.element.Tag):
            tds = tr('td')
            ulist.append([tds[0].string, tds[1].string, tds[4].string])


def printUnivList(ulist, num):
    tplt = "{0:^10}\t{1:{3}^10}\t{2:^10}"
    print(tplt.format("排名", "学校", "总分", chr(12288)))
    for i in range(num):
        u = ulist[i]
        print(tplt.format(u[0], u[1], u[2], chr(12288)))


def main():
    uinfo = []
    url = 'http://www.zuihaodaxue.com/zuihaodaxuepaiming2020.html'
    html = getHTMLText(url)
    fillUnivList(uinfo, html)
    printUnivList(uinfo, 20)

main()

参考资料:
【1】Mooc - Python爬虫与信息提取

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值