掌握定向网络数据爬取和网页解析的基本能力
总体架构:
Requests库:自动爬取HTML页面、自动网络提交请求
robots.txt:网络爬虫排除标准,合理合法的使用爬虫爬取内容
Beautiful Soup库:解析HTML界面
实战项目A/B:练习
Re库:正则表达式需要用到re模块,用于提取页面关键信息
Scrapy*:网络爬虫原理介绍,专业爬虫框架介绍,用于中规模、速度更快的爬虫
环境:pycharm、python3.7
一:环境搭建
1:下载pycharm:https://www.jetbrains.com/pycharm/download/#section=windows
选择Community(For pure Python development)下载完成安装。
2:安装anaconda:
python选择anaconda3这个集成环境,下载地址:https://mirrors.tuna.tsinghua.edu.cn/#
安装anaconda3时,最后有一个选项设置环境变量,记得选中。
3:为pycharm设置python环境:
configure->settings->
选择anaconda目录下的python.exe文件。如下图。点击Apply。
点击create创建一个工程。
4:安装requests库:
在pycharm中点击file->settings->
如果报错:AttributeError: ‘module’ object has no attribute ‘main’,参考这篇博客:https://blog.csdn.net/qq_38132105/article/details/104188943
升级pip3的版本后,再安装requests库。
Requests库
1:Requests库的七个主要方法:
(1):get()方法
requests.get(url, params=None, **kwargs)
url:要获取页面的url链接
params:url中的额外参数,字典或字节流格式,可选
**kwargs:12个控制访问的参数
我们打开get()方法的源代码,会发现get()方法调用了request()方法,实际上get()方法,post()方法都是通过调用request()方法实现的。
调用requests.get()方法会产生两个重要对象Response和Request
Response对象返回所有的网页内容
变量r中存储的是名为Response的类对象
r.encoding只是从HTTP header中猜测的响应内容编码方式
r.apparent_encoding是从内容中分析出的响应内容编码方式(备选编码方式),但这种编码方式更为准确。如下方代码,设置http://www.baidu.com的编码方式r.encoding = ‘ISO-8859-1’
仍然会有乱码。
设置r.encoding = r.apparent_encoding即’utf-8’,如下图
r.encoding字段的值是从r.headers返回的charset字段中获得的,如果header中不存在charset字段,则认为编码为ISO-8859-1。
但ISO-8859-1不能解析中文,所以requests库提供了另一个方法apparent_encoding。
2:爬取网页的同通用代码框架
requests.get(url)获得url的相关内容,但是这样的语句并不是一定成立的,因为网络连接有风险(如反爬虫),异常处理很重要
Requests库提供的六种常用的处理异常的方法:
requests.ConnectTimeout与requests.Timeout的区别:
requests.ConnectTimeout是指发出url请求到或的内容整个过程的超时异常。
requests.Timeout仅指与远程服务器连接过程中超时产生的异常。
Response对象提供了一个与异常有关的方法:
r.raise_for_status(),这个方法能够判断返回的Response类型 r 的status是不是200,如果是200,表示返回的内容是正确的,如果不是200,那么这个方法就会产生一个requests.HTTPError的异常。
红框中的内容是通用代码框架。通用代码框架实际上最大的作用是能够使用户访问或爬取网页变得更有效、更稳定、更可靠。
3:HTTP协议及Requests库方法
HTTP:Hypertext Transfer Protocol,超文本传输协议
HTTP是一个基于“请求与响应”模式的、无状态的应用层协议。
HTTP协议采用URL作为定位网络资源的标识。
URL格式 http://host[:port][path]
host:合法的Internet主机域名或IP地址
port:端口号,缺省端口为80
path:请求资源的路径
HTTP URL的理解:
URL是通过HTTP协议存取资源的Internet路径,一个URL对应一个数据资源。
理解PATCH和PUT的区别:
假设URL位置有一组数据UserInfo,包括UserID、UserName等20个字段。
需求:用户修改了UserName,其他不变。
- 采用PATCH,仅向URL提交UserName的局部更新请求。节省网络带宽。
- 采用PUT,必须将所有20个字段一并提交到URL,未提交字段被删除。
下面重点介绍几个方法:
requests.head()方法:用requests.head()方法获取资源的信息时,只能获取到i做议案的头部信息,故用r.text显示资源的全部信息时,为空字符串。head()方法可以用很少的网络流量获取网络资源的概要信息。
用requests.post()方法向URLpost一个字典,或者一个键值对的时候,字典或键值对会被默认的存储到表单的字段下。
若post的数据为字符串,则默认存储到data字段下。
requests.put()方法与post()类似,但put()方法会将原有的数据覆盖掉。
4:Requests库七个主要方法解析
requests.request(method, url, **kwargs)
method:请求方式,对应get/put/post等7种
url:拟获取页面的url链接
**kwargs:控制访问的参数,共13个
r = requests.request(‘POST’, ‘http://python123.io/ws’, headers=hd):表示访问目标服务器 ‘http://python123.io/ws’ 时,服务器看到的user-agebt字段的值是’Chrome/10’,利用这种方式,可以冒充任意浏览器的任意版本向服务器发起访问。
file参数可以向某一个链接提交文件。
当我们你发起一个GET请求时,我们可以设置一个timeout时间,如果在timeout时间内,我们请求的内容没有返回回来,会产生一个timeout异常。
这里增加两个代理:一个是http访问时使用的代理,在代理中可以增加用户名跟密码的设置。另一个是https访问时使用的代理服务器。那么我们访问http://www.baidu.com时的IP地址就是代理服务器的IP地址,使用proxies这个字段可以有效地隐藏用户爬取网页的源的IP地址信息,能够有效的防止对爬虫的逆追踪。
requests.get(url, params=None, **kwargs)
requests.head(url, **kwargs)
requests.post(url, data=None, json=None, **kwargs)
requests.put(url, data=None, **kwargs)
requests.patch(url, data=None, **kwargs)
requests.delete(url, **kwargs)
5:网络爬虫引发的问题
对服务器性能骚扰问题、内容层面的法律风险问题、个人隐私泄露问题
网络爬虫的限制
6:Robots协议
Robots Exclusion Standard 网络爬虫排除标准
作用:告知网络爬虫网站的哪些页面可以抓取,哪些不行
基本语法
# *代表所有网络爬虫使用的所有客户端
# /代表根目录
User-agent:*
Disallow:/
7:Robots协议的遵守方式
Robots协议的使用
网络爬虫应该能够自动或者人工识别robots.txt,再进行内容爬取。
类人行为可不参考Robots协议。
8:京东页面商品的爬取
下方是带有爬虫框架的全代码:
import requests
url = "http://item.jd.com/2967929.html"
try:
r = requests.get(url)
# raise_for_status()方法判断返回的代码是不是200
# 不是200则产生异常
r.raise_for_status()
r.encoding = r.apparent_encoding
print("r.text[:1000]")
except:
print("爬取失败")
9:亚马逊商品页面的爬取
我们观察r.text返回的内容:
我们来查看一下客户端发送给服务器的请求的headers
使用Response对象中包含的request对象的headers信息r.request.headers
r.headers返回的是服务器端发送回来的headers信息
r.request.headers返回的是客户端发送给服务器端请求的headers信息
我们可以看到返回的结果中User-agent字段的值为’python-requests/2.22.0’,即我们编写的爬虫忠实的告诉了amazon的服务器,这次访问是由一个python的requests库的程序产生的。
我们可以更改客户端发送请求的头部信息,来模拟浏览器向amazon进行访问。
全代码:
10:百度/360搜索关键词提交
向百度或者360搜索提交关键词,并返回搜索的结果:
只要我们替换keyword,就可以向搜索引擎提交关键词了。
构造一个URL链接,这个链接包含我们要搜索的关键词。
向百度提交关键词的全代码:
向360提交关键词的全代码:
11:网络图片的爬取和存储
图片爬取全代码:
使用open()方法时,由于文件读写时都有可能产生IOError,一旦出错,后面的f.close()就不会调用。所以,为了保证无论是否出错都能正确地关闭文件,我们可以下方代码:
try:
f = open('/.../file', 'r')
print(f.read())
finally:
if f:
f.close()
Python引入了with语句来自动帮我们调用close()方法:
with open('/.../file', 'r') as f:
print(f.read())
模式 | 描述 |
---|---|
w | 打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件 |
w+ | 打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件。 |
wb | 以二进制格式打开一个文件只用于写入。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件 |
wb+ | 以二进制格式打开一个文件用于读写。如果该文件已存在则打开文件,并从开头开始编辑,即原有内容会被删除。如果该文件不存在,创建新文件 |
import requests
import os
url = "http://img0.dili360.com/pic/2020/01/03/5e0ee523da2ad0t04429317.jpg"
root = "D://pics//"
path = root + url.split('/')[-1]
try:
if not os.path.exists(root):
os.mkdir(root)
if not os.path.exists(path):
r = requests.get(url)
with open(path, 'wb') as f:
f.write(r.content)
f.close()
print("文件保存成功")
else:
print("文件已存在")
except Exception as e:
print(e)
12:IP地址归属地的自动查询
IP地址归属地自动查询全代码:
import requests
url = "http://m.ip138.com/ip.asp?ip="
try:
r = requests.get(url + '202.204.80.112')
r.raise_for_status()
print(r.status_code)
r.encoding = r.apparent_encoding
# print(r.request.headers)
print(r.text[-500:])
except:
print("爬取失败")
13:Beautiful Soup库的使用
Beautiful Soup库是能够解析HTML和XML的库。
import requests
r = requests.get("https://python123.io/ws/demo.html")
demo = r.text
from bs4 import BeautifulSoup
soup = BeautifulSoup(demo, "html.parser")
print(soup.prettify())
‘html.parser’:指定解析器是html格式的parser
这里边的BeautifulSoup是一个类,上边代码用于解析HTML或XML信息。
13:Beautiful Soup库的基本元素
属性Attributes使用来定义标签的特点的。
一个HTML和一个标签树是一一对应的,经过BeautifulSoup类的处理,将标签树转换成BeautifulSoup类,BeautifulSoup类就是能够代表标签树的一个类型。事实上我们认为HTML文档,标签树,BeautifulSoup类是等价的。在这个等价的基础上,我们就可以通过BeautifulSoup类使得标签树形成一个变量,而对这个变量的处理就是对标签树的处理。
以下是引入html文本的两种方式:
(1):直接放入HTML源码
(2):通过打开文件的方式,传入HTML源码
BeautifulSoup类对应一个HTML/XML文档的全部内容
Beautiful Soup库的解析器:
对上图的解释:
Tag:如a标签、title标签
Name:如a.name、title.name
Attributes:如a.attrs、title.attrs
NavigableString:如<\title>title中间的内容</title>调用soup.title.string返回’title中间的内容’,即两个标签中间的字符串
Comment:如果HTML页面中出现有注释的部分,该如何应对
Tag
Name
a.name返回’a’,title.name返回’title’,p.name返回’p’
Attributes
NavigableString
我们看到在p标签中还有一个b标签,但soup.p.string中并没有包含b标签,这说明NavigableString是可以阔约多个标签层次的。
Comment
在实际开发中,要判断标签的内容是不是注释,需要用type()方法判断一下,但在开发中这种情况并不常见,了解即可。
14:基于bs4库的HTML内容遍历方法
未完待续:https://www.bilibili.com/video/av9784617?p=7