爬虫基础——urllib库与正则表达式

本文主讲:了解什么是爬虫、urllib请求库的使用、正则表达式的使用等…..

什么是爬虫及其分类!

什么是网络爬虫?

答:网络爬虫就是利用一段程序模拟人操作浏览器获取数据的过程,且模拟人操作浏览器越逼真越好!

网络爬虫的分类

通用爬虫:浏览器所用的爬虫,需要遵守 robots 君子协议

聚焦爬虫:针对一些特定网页获取数据

功能爬虫:利用爬虫实现一些功能,如自动投票、自动抢票等

数据爬虫:利用爬虫获取一些指定网页的数据!

注意事项:在网站的根目录下输入 /robots.txt 可查看网站的 robots 协议

image-20211013092323280

爬虫爬取数据的步骤!

爬虫获取数据的步骤!

第一:找到需要爬取数据的 url 地址

第二:(包装请求头)向这个 url 地址发起请求

第三:获取这个 url 服务器发来的响应数据(网页源代码)

第四:利用 python 数据解析库在源码中获得想要的数据!

第五:将数据进行清洗保存(csv、数据库、Excel)!

第六:是否需要在原网页内进行链接跳转再抓取数据!

urllib.request库的方法及功能【重点】

urllib.request 库内的 urlopen()方法功能

功能:向目标 url 发送一个请求,并返回一个相应对象

方法参数:

url:发送请求的目标网站(网站一定要写全 例如 http://www.baidu.com/ ,http不能忘以及最后的/)

timeout:设置请求时间,超过设置的请求时间将抛出异常

语法:res_obj = urllib.request.urlopen(url)

注意:res_obj 只是网站响应的对象,不是网站相应的数据!!!

urllib.request.urlopen()方法返回的响应对象的方法

响应对象.read():获取网站响应的源代码(bytes数据格式)【字节串数据格式】

响应对象.read.decode(编码格式):获取网站响应的源代码(string数据格式)【字符串数据格式】

响应对象.geturl():获取实际返回响应数据的网站url(考虑到重定向问题)

响应对象.getcode():获取网站的http响应状态码

注意: bytes数据与string数据不一样,bytes是以字节为单位,string是以字符为单位, string通过encode()编码可转换为bytes,bytes可通过decode()解码转换为string,bytes数据格式为 b“数据”,string数据格式为 “数据”

图示:

响应对象的.read()方法

image-20211013092402556

响应对象的.read().decode()方法

image-20211013092409918

响应对象的.geturl()与响应对象的.getcode()方法

image-20211013092417285

怎么查看程序向网站发送请求时标头的 User-Agent

直接向下面 url 地址发送请求即可查看请求协议标头的 User-Agent

网站:http://httpbin.org/get

图示:

浏览器发送请求查看 User-Agent

image-20211013092437732

python的urllib库发送请求查看 User-Agent

image-20211013092445366

urllib.request库内的 Request()方法功能

功能:包装请求标头信息(一般是 User-Agent),并且返回这个包装好的请求头对象,用于向 url 发送请求

语法:req = urllib.request.Request(url = 网站域名,headers = {“User-Agent”:“伪装的标头信息”})

参数:

url:待请求的链接地址

headers:伪装的请求标头信息

注意事项:Request方法并没有向网站发送请求,而是伪装请求标头,urlopen方法才向目标网站发送请求并且接收响应数据

截图

image-20211013092505732

urllib.parse模块的方法功能解析【重点】

目标:

1:掌握搜索关键字 url 地址的组成部分

2:掌握向目标查询关键字地址发送请求的注意事项

3:urllib.parse.urlencode()方法详解

4:urllib.parse.quote()方法详解

5:掌握 urllib.parse库内的 urlencode 方法以及 quote 方法的区别~

搜索关键字 url 地址的组成部分

组成:协议项+域名+数据库资源路径+查询参数

图示:

image-20211013092521994

注意:其实很多查询参数都没有用,上面的 url 可简化为 https://www.baidu.com/s?wd=美女

向查询关键字地址服务器发送请求的注意事项

什么是查询关键字地址?:就是搜索相应关键字所对应的url地址,例如在百度上查询美女的url地址如下

https://www.baidu.com/s?wd=美女

向查询关键字地址服务器发送请求的注意事项:需要将url地址内中文 编码后 才可以向服务器发送请求

示例:

编码前URL地址:https://www.baidu.com/s?wd=美女

编码后URL地址:https://www.baidu.com/s?wd=%E7%BE%8E%E5%A5%B3

注意:编码后三个%对应一个中文字符,例如%E7%BE%8E就对应 美 这个中文字符

urllib.parse.urlencode()方法详解

功能:将查询参数内的中文进行编码,并返回编码后的查询参数(返回多个编码后的查询参数时默认返回 &)

语法:返回编码后查询参数 = urllib.parse.urlencode({查询参数1:待编码值1,查询参数2:待编码值2……….})

语法参数:

字典:字典内存放需要编码的查询参数,例如查询参数为 wd=美女 就这么写 {“wd”:“美女”}

语法参数返回值:

params = urllib.parse.urlencode({“wd”:“美女”}) params 就是 wd=%E7%BE%8E%E5%A5%B3

注意事项:urllib.parse.urlencode()方法只返回编码后的查询参数,并不是整个url地址,需要进行字符串拼接才能向目标url服务器发送请求

图示:

image-20211013092600107

urllib.parse.quote()方法详解

功能:对查询参数内的中文进行编码,并且返回这个中文编码后的字符串

语法:编码后的中文字符串 = urllib.parse.quote(”查询参数中的中文关键字“)

例如:params = urllib.parse.quote(”美女“) params 就是 %E7%BE%8E%E5%A5%B3

方法参数:

查询参数内的中文:只是中文,没有相对应的 wd 等

注意事项:这个方法只返回编码后的中文字符,连键都不返回需要自己写

图示:

image-20211013092614582

urllib.parse库内的 urlencode 方法以及 quote 方法的区别~

区别:

1:参数不同,urlencode参数为字典,quote参数是中文字符串

2:返回值不同,urldecode返回的是键与值,例如 wd=%E7%BE%8E%E5%A5%B3 ,quote方法返回的只有值,例如 %E7%BE%8E%E5%A5%B3

简单爬虫的构架【重点】

简单爬虫的老版本构架(面向对象编程)

可保存至电脑放大来看!

简单爬虫的新版本构架(面向对象编程)

正则模块(re)的使用【重点】

正则模块 re 抓取数据的两种方法形式

第一种形式(直接使用findall(查找数据)方法):

data_list = re.findall(正则表达式,待匹配字符串,re.S)

第二种形式(先创建正则编译对象在调用findall等方法):

pattern = re.compile(正则表达式,re.S)
data_list = pattern.findall(待匹配字符串)

注意事项:一般大佬都用第二种形式,因为正则写好一个可以多次调用

图示:

image-20211013092723573

正则模块 re 方法的 re.S参数的作用

作用:正则表达式中的元字符 . 可以匹配任意字符(除了换行符/n),在findall等方法内部加上参数 re.S后 元字符 . 就可以匹配换行符/n啦

注意:在抓取 html 代码时一定不要忘记写 re.S参数,因为 html 代码有很多换行符

图示:

image-20211013092734436

正则表达式贪婪模式以及非贪婪模式的注意事项

元字符 ?功能: ? 前一个字符出现1次或者0次

贪婪模式:在满足匹配规则的前提下尽可能多的匹配数据

非贪婪模式:在满足匹配规则的前提下尽可能少的匹配数据

注意事项:

1:贪婪模式与非贪婪模式说的都是在匹配多个字符时才适用,即元字符 * + ?

2:python程序默认是贪婪模式匹配数据

3:在匹配多个数据的元字符(* + ?)后面加上 ? 就可将贪婪模式转变为非贪婪模式,注意一定是在匹配多个元字符后面加才管用!!!

正则表达式单个分组以及多个分组的用法

用法【单个分组】:如果在正则表达式的一部分加上单个分组,也就是一个() 那么在调用 findall方法时,只将符合分组内的数据提取到列表内!

用法【多个分组】:如果在正则表达式的一部分加上多个分组,也就是多个() 那么在调用 findall方法时,将符合多个分组内的数据先保存到一个元组内,然后在匹配其他符合分组的数据,再次存放到另一个元组内,然后在将多个元组存放至列表中【列表内嵌套元组】

图示【单个分组】 【多个分组】:

image-20211013092752765

正则表达式匹配html数据的技巧【重点】

目标:掌握正则表达式匹配 html 代码的技巧

正则表达式匹配 html 代码的技巧

实例html代码如下(提取电影名、主演、上映时间):

image-20211013092804554

正则表达式可以这么写!!

对应的正则表达式:

1
<div class="movie-item-info">.*?<a href="/films/[0-9]+" title="(.*?)".*?<p class="star">\s+主演:(.*?)\s+</p>\s+<p class="releasetime">上映时间:(.*?)</p>

书写正则的技巧:

1:第一个包含类的标签一定要写出来(例如 <div class="movie-item-info">)这样正则可一下就找出来匹配的数据在那个标签类

2:待匹配的数据要加上分组,一般都是这么写 (.*?),这样可被findall方法直接匹配出来

3:待匹配数据的前一个标签一般要按照给出的写出来(也可以不写!)

4:.*?正则表达式是一个很好的东西哦,一定要学会使用!!!

5:因为加上了 re.S 参数,所以 . 可以匹配任何数据

图示:

image-20211013092844399

未完待续……