1.认识爬虫
我们所熟悉的一系列搜索引擎都是大型的网络爬虫,比如百度、搜狗、360浏览器、谷歌搜索等。每个搜索引擎都拥有自己的爬虫程序,比如360浏览器的爬虫称作360Spider,搜狗的爬虫叫做Sogouapider
2.爬虫分类
爬虫可分为三大类:通用网络爬虫、聚焦网络爬虫、增量式网络爬虫
通用网络爬虫:是搜索引擎的重要组成部分,通用网络爬虫需要遵守robots协议,网站通过此协议告诉搜索引擎哪些页面可以抓取,哪些页面不可以抓取
聚焦网络爬虫:是面向特定需求的一种网络爬虫程序,它与通用爬虫的区别在于,聚焦爬虫在实施网页抓取的时候会对网页内容进行筛选和处理,尽量保证只抓取与需求相关的网页信息,聚焦网络爬虫极大地节省了硬件和网络资源,由于保存的页面数量少所以更新速度很快。
增量式网络爬虫:是指对已下载网页采取增量式更新,它是一种只爬取新产生的或者已经发生变化网页的爬虫程序,能够在一定程度上保证爬取的页面时最新的页面
3.爬虫应用
1).数据分析
2).商业领域
4.为什么用python做爬虫
不止python这一种语言可以做爬虫,诸如php、java、c/c++都可以用来写爬虫程序,但是相较于其他语言python做爬虫是最简单的
php:对多线程、异步的支持语言不是很好java也经常用来写爬虫程序,但java:java语言本身很笨重,代码量大,因此入门的门槛较高;
c/c++:c/c++运行效率虽然高,但学习和开发成本也高,写一个小型的爬虫程序可能花费很长的时间
而python语言,其语法优美,代码简洁,开发效率高,支持·多个爬虫模块,比如urllib、requests、Bs4等。python的请求模块和解析模块丰富成熟,并且提供了强大的Scrapy框架,让写爬虫程序变得更为简单
5.编写python爬虫的流程
- 先由urllib模块的request方法打开url得到网页HTML对象
- 使用浏览器打开网页源代码分析网页结构以及元素节点
- 通过Beautiful Soup或者正则表达式提取数据
- 存储数据到本地磁盘或数据库
6.简单的python爬虫程序
6-1.获取网页html信息
获取响应对象
向百度(http://www.baidu.com/)发起请求,获取百度首页的html信息,代码如下
import urllib.request
#或from urllib import request
#response = request.urlopen('http://www.baidu.com/')
resonse=urllib.request.urlopen('http://www.baidu.com/')
6-2.输出HTML信息
#提取响应内容
html=response.read().decode('utf-8')
urllib常用方法
1).urlopen(url,timeout)
url:表示要爬取的url地址
timeout:设置等待超时时间,指定时间内未得到响应则抛出超时异常
2).urllib.request.Request(url,headers)
url:请求的URL地址
headers:重构请求头
html响应对象方法
bytes=response.read()#read()返回结果为bytes数据类型
string=response.read().decode()#decode()将字节串转换为string类型
url=response.geturl()#返回响应对象的url地址
code=response.getcode()#返回请求时的HTTP响应码
编码解码操作
string.encode('utf-8')#字符串转换为字节码
bytes.decode('utf-8')#字节码转换为字符串
7.User-Agent(用户代理)是什么
User-Agent即用户代理,简称UA,它是一个特殊字符串头。网站服务器通过识别UA来确定用户所使用的操作系统版本、CPU类型、浏览器版本等信息。而网站服务器则通过判断UA来给客户端发送不同的页面
网络爬虫使用程序代码网站,因此爬虫程序也被称为网络机器人,绝大多数网站都具备一定的反爬能力,禁止爬虫大量的访问网站,以免给网站服务器带来压力,User-Agent就是反爬策略的第一步
网站通过识别请求头中User-Agent信息来判断是否是爬虫访问网站。如果是,网站首先对该IP进行预警,对其进行重点监控,当发现该IP超过规定时间内的访问次数,将在一段时间内禁止再次访问网站
常见的 User-Agent 请求头,如下所示:
系统 | 浏览器 | User-Agent字符串 |
---|---|---|
Mac | Chrome | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/73.0.3683.75 Safari/537.36 |
Mac | Firefox | Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:65.0) Gecko/20100101 Firefox/65.0 |
Mac | Safari | Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_6) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/12.0.3 Safari/605.1.15 |
Windows | Edge | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.140 Safari/537.36 Edge/18.17763 |
Windows | IE | Mozilla/5.0 (Windows NT 10.0; WOW64; Trident/7.0; rv:11.0) like Gecko |
Windows | Chrome | Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.121 Safari/537.36 |
iOS | Chrome | Mozilla/5.0 (iPhone; CPU iPhone OS 7_0_4 like Mac OS X) AppleWebKit/537.51.1 (KHTML, like Gecko) CriOS/31.0.1650.18 Mobile/11B554a Safari/8536.25 |
iOS | Safari | Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12F70 Safari/600.1.4 |
Android | Chrome | Mozilla/5.0 (Linux; Android 4.2.1; M040 Build/JOP40D) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.59 Mobile Safari/537.36 |
Android | Webkit | Mozilla/5.0 (Linux; U; Android 4.4.4; zh-cn; M351 Build/KTU84P) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30 |
注:httpbin.org这个网站能测试HTTP请求和响应的各种信息,比如cookie、IP、headers和登录验证等,且支持GET/POST等多种方法
重构爬虫信息
下面使用urllib.request.Request()方法重构User-Agent信息,代码如下:
import urllib.request
url = 'http://httpbin.org/get' #向测试网站发送请求
#重构请求头,伪装成 Mac火狐浏览器访问,可以使用上表中任意浏览器的UA信息
headers = {
'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:65.0) Gecko/20100101 Firefox/65.0'}
# 1、创建请求对象,包装ua信息
req = urllib.request.Request(url=url,headers=headers)
# 2、发送请求,获取响应对象
res = urllib.request.urlopen(req)
# 3、提取响应内容
html = res.read().decode('utf-8')
print(html)
重构UA
也可以通过其他模块实现,比如requests模块
8.自定义UA代理池
在编写爬虫程序的时候,一般会构建一个UA(用户代理)池,就是把多个浏览器的UA信息放进列表中,再从中随机选择,构建用户代理池,能够避免总是使用一个UA来访问王者,因为短时间总是用一个UA高频率访问的网站,可能会引起网站的警觉,从而封杀掉IP
构建代理池的方法也非常简单,在您的pycharm工作目录中定义一个ua_info.py文件,将UA信息以列表的形式粘贴到该文件中,也可以使用专门的第三方模块来随机获取UA信息,不过需要安装
pip install fake-useragent
from fake_useragent import UserAgent
#实例化一个对象
ua=UserAgent()
9.URL编码/解码详解
当URL或者查询参数中,带有中文或者特殊字符的时候,就需要对URL进行编码(采用十六进制编码格式),URL的编码原则是使用安全字符去表示那些不安全字符
注:安全字符,指的是没有特殊用途或者特殊意义的字符
URL中规定了一些具有特殊意义的字符,常用来分隔两个不同的URL组件,这些字符被称为保留字符,例如:
- 冒号:用于分隔协议和主机组件,斜杠用于分隔主机和路径
- ?:用于分隔路径和查询参数等
- =:用于查询参数中的键值对
- &:用于分隔查询的多个键值对
其余常用的保留字符有:/ . ... # @ $ + ; %
10.哪些字符需要编码
URL之所以需要编码,是因为URL中的某些字符会引起歧义,比如URL查询参数中包含了&或者%就会造成服务器解析错误;再比如,URL的编码格式采用的是ASCII码而非Unicode格式,这表明URL中不允许包任何非ASCII字符(比如中文),否则就会造成URL解析错误
URL编码协议规定(RFC3986协议):URL中只允许使用ASCII字符集可以显示的字符,比如英文字母、数字、和- _ . ~ ! *这6个特殊字符,当在URL中使用不属于ASCII字符集的字符时,就要使用特殊的符号对该字符进行编码,比如空格需要%20来表示
除了无法显示的字符需要编码外,还需要对URL中的部分保留字符和不安全字符进行编码,下面列举了部分不安全字符:
[ ] < > " " { } | \ ^ * · ‘ ’ 等
下表对URL中部分保留字符和不安全字符进行了说明:
字符 | 含义 | 十六进制值编码 |
---|---|---|
+ | URL中+号表示空格 | %2B |
空格 | URL中空格可以编码为+号或者%20 | %20 |
/ | 分隔目录和子目录 | %2F |
? | 分隔实际的URL和参数 | %3F |
% | 指定特殊字符 | %25 |
# | 表示书签 | %23 |
& | URL中指定的参数间的分隔符 | %26 |
= | URL中指定参数的值 | %3D |
11.python实现编码与解码
python的标准库urllib.parse模块中提供了用来编码和解码的方法,分别是urlcode()与unquote()方法
urlencode():该方法实现了对url地址的编码操作
unquote():该方法将编码后的url地址进行还原,也就是解码
12.爬虫程序结构
用面向对象的方法编写爬虫程序时,逻辑结构较为固定
#程序结构
class xxxSpider(object):
def __init__(self):
#定义常用的变量,比如url或计数变量等
def get_html(self):
#获取响应内容的函数,使用随机的User-Agent
def parse_html(self):
#使用正则表达式来解析页面,提取数据
def write_html(self):
#将提取的数据按要求进行保存,csv,MYSQL数据库等
def run(self):
#主函数,用来控制整体逻辑
if __name__=='__main__':
#程序开始运行时间
spider=xxxSpider()
spider.run()
13.正则表达式基本语法
正则表达式是一种字符串匹配模式或者规则,它可以用来检索、替换那些符合规定的文本,正则表达式几乎适用于所有的编程语言,无论是前端语言javascript还是诸如许多后端语言,比如python、java、c#等,这些都提供了相应的函数、模块来支持正则表达式,比如python的re模块
在使用python'编写爬虫的过程中,re模块通常作为一种解析方法来使用,通过审查网页元素来获取网页的大体结构,然后使用解析模块来提取你想要的网页信息,最终实现数据的抓取
正则表达式元字符
元字符 | 匹配内容 |
---|---|
. | 匹配除换行符以外的任意字符 |
\w | 匹配所有普通字符(数字、字母或下划线) |
\s | 匹配任意的空白符 |
\d | 匹配所有数字 |
\n | 匹配一个换行符 |
\t | 匹配一个制表符 |
\b | 匹配一个单词的结尾 |
^ | 匹配字符串的开始位置 |
$ | 匹配字符串的结尾位置 |
\W | 匹配非字母或数字或下划线 |
\D | 匹配非数字 |
\S | 匹配非空白符 |
a|b | 匹配字符a或字符b |
() | 正则表达式分组所用符号,匹配括号内的表达式,表示一个组 |
[...] | 匹配字符组中的字符 |
[^...] | 匹配除了字符组中的所有字符 |
量词
量词 | 匹配内容 |
---|---|
* | 重复零次或更多次 |
+ | 重复一次或者更多次 |
? | 重复0次或者一次 |
{n} | 重复n次 |
{n,} | 重复n次或者更多次 |
{n,m} | 重复n到m次 |
字符组
正则 | 待匹配字符 | 匹配结果 | 说明 |
---|---|---|---|
[0123456789] | 8 | True | 在一个字符组里枚举所有字符,字符组里的任意一个字符和"待匹配字符"相同都视为可以匹配。 |
[0123456789] | a | False | 由于字符组中没有a字符,所以不能匹配 |
[0-9] | 7 | True | 也可以用-表示范围,[0-9] 就和 [0123456789] 是一个意思。 |
[a-z] | s | True | 匹配所有的小写字母,直接用 [a-z] 就可以表示 |
[A-Z] | B | True | [A-Z] 就表示所有的大写字母 |
[0-9a-fA-F] | e | True | 可以匹配数字,大小写形式的 a~f,用来验证十六进制字符 |
贪婪模式
正则模式默认为贪婪匹配,也就是尽可能多的向后匹配字符,比如{n,m}表示前面的内容出现n到m次(n小于m),在贪婪模式下,首先以匹配m次为目标,而在非贪婪模式是尽可能少的向后匹配内容,也就是说匹配n次即可,贪婪模式转换为非贪婪模式在元字符后添加?即可实现
14.re模块用法详解
re模块常用方法
re.compile()该方法用来生成正则表达式对象,其语法格式如下:
regex=re.compile(pattern,flags=0)
参数说明:
pattern:正则表达式对象
flags:代表功能标志位,扩展正则表达式的匹配
re.findall()根据正则表达式匹配字符串内容
re.findall(pattern,string,flags=0)
该函数的返回值是匹配到的内容列表,如果正则表达式有子组,则只能获取到子组对应的内容,参数说明如下:
pattern:正则表达式对象
string:目标字符串
flags:代表功能标志位,扩展正则表达式的匹配
regex.findall()该函数根据正则表达式对象匹配目标字符串内容,其语法格式如下:
regex.findall(string,pos,endpos)
参数说明:
string 目标字符串。
pos 截取目标字符串的开始匹配位置。
endpos 截取目标字符串的结束匹配位置。
re.split(pattern,string,flag=0)该函数使用正则表达式匹配内容,切割目标字符串。返回值是切割后的内容列表
re.split(pattern,string,flags = 0)
参数说明:
pattern:正则表达式。
string:目标字符串。
flags:功能标志位,扩展正则表达式的匹配。
re.sub()该参数使用一个字符串替换正则表达式匹配到的内容,返回值是替换后的字符串。其语法格式如下:
re.sub(payyern,replace,string,max,flags=0)
其参数说明:
pattern:正则表达式
replace:替换的字符串
string:目标字符串
max:最多替换几处,默认替换全部
flags:功能标志位,扩展正则表达式的匹配
re.search匹配目标字符串第一个符合的内容,返回值为匹配的对象,语法格式如下:
re.search(pattern,string,flags=0)
flags功能标志位
功能标志位的作用是扩展正则表达的匹配功能,常用的flag如下所示:
缩写元字符 | 说明 |
---|---|
A | 元字符只能匹配ASCII码 |
I | 匹配忽略字母大小写 |
S | 使得.元字符可以匹配换行符 |
M | 使^$可以匹配每一行的开头和结尾位置 |
15.csv模块(读写文件)
csv文件又称为逗号分隔值文件,是一种通用的、相对简单的文件格式,用以存储表格数据,包括数字或者字符。csv是电子表格和数据库中最常见的输入、输出文件格式。
通过爬虫将数据抓取下来,然后吧数据保存在文件,或者数据库中,这个过程称为数据的持久化存储。
csv文件写入
csv.writer()csv模块中的writer类可用于读写序列化的数据,其语法格式如下:
writer(csvfile,dialect=‘excel’,**fmtparams)
参数说明:
csvfile:必须是支持迭代(iterator)的对象,可以是文件(file)对象或者列表(list)对象
dialect:编码风格,默认为excel,也就是使用逗号分隔
fmtparam:格式化参数。用来覆盖之前dialect对象指定的编码风格

16.csv文件读取
csv.reader()csv模块中的reader类和DictReader类用于读取文件中的数据,其中reader()语法格式如下:
csv.reader(csvfile, dialect='excel', **fmtparams)
17.Pymysql实现数据存储
连接数据库
db=pymysql.connect('localhost','root','123456',maoyandb)
参数说明:
localhost:本地 MySQL 服务端地址,也可以是远程数据库的 IP 地址。
root:连接数据所使用的用户名。
password:连接数据库使用的密码,本机 MySQL 服务端密码“123456”。
db:连接的数据库名称。
创建cursor对象
cursor=db.cursor()
执行sql命令
execute()方法用来执行SQL语句
例:
sql='insert into filmtab values('%s','%s','%s')' % ('刺杀,小说家','雷佳音','2021')
cursor.execute(sql)
sql='insert into filmtab values('%s','%s','%s')'
cursor.execute(sql,['刺杀,小说家','雷佳音','2021'])
提交数据
db.commit()
关闭数据库
cursor.close()
db.close()
插入多条
使用executemany()可以同时插入多条数据
18.爬虫增量抓取
爬虫是一种效率很低的程序,非常消耗计算机资源,对于聚焦爬虫程序而言,需要每天对特定的网站进行数据抓取,如果每次都去抓取之前意境抓取过的数据,就会白白消耗了时间和资源,而增量爬虫是指通过监测网站更新的
那么要如何判断爬虫程序是否已经抓取过二级页面的url呢,其实,当你第一次运行爬虫程序时,爬虫会将所有的url抓取下来,然后将这些url放入数据库中,为了提高数据库的查询效率,您可以为每一个url生成专属的标识,当网站更新后,程序只会对数据库中不存在的标识进行抓取
代码实现:
建库建表
create datebase movieskydb charset utf8;
use movieskydb;
create table request_finger(
finger char(60)
)charext=utf8;
create table movieinfo(
moviename varchar(300),
downloadaddr varchar(600)
)charset=utf8;
url标识生成
可以使用python内置模块md5来生成加密标识
#导入模块
from hashlib import md5
#待加密的url
url="https://www.dytt8.net/html/gndy/dyzz/20210226/61131.html"
# 生成MD5对象
secret = md5()
# 加密url
secret.update(url.encode())
# 提取十六进制的加密串
finger = secret.hexdigest()
19.python requests库安装与使用
requests库的宗旨是让http服务于人类
requests.get()
该方法用于 GET 请求,表示向网站发起请求,获取页面响应对象。语法如下:
res = requests.get(url,headers=headers,params,timeout)
参数说明如下:
url:要抓取的 url 地址。
headers:用于包装请求头信息。
params:请求时携带的查询字符串参数。
timeout:超时时间,超过时间会抛出异常。
例:
import requests
url = 'http://baidu.com'
response = requests.get(url)
print(response)
requests.post()
该方法用于 POST 请求,先由用户向目标 url 提交数据,然后服务器返回一个 HttpResponse 响应对象,语法如下:
response=requests.post(url,data={请求体的字典})
requests库常用方法及参数介绍
requests.request()构造一个请求对象,该方法是实现以下各个方法的基础
requests.get()获取html网页的主要方法
requests.head()获取html网页头信息的方法
requests.post()获取html网页post请求方法
requests.put()获取html网页put请求方法
requests.patch()获取html网页提交局部修改请求
requests.delete()获取html页面提交删除请求
20.SSL认证-verifyu参数
SSL证书是数字证书的一种,SSL证书遵守SSL协议,由信任的数字证书颁发机构 CA(电子认证服务)颁发。 SSL 具有服务器身份验证和数据传输加密功能。
verify参数的作用是检查SSL认证,默认是True,设置为False则不检查SSL证书
21.proxies参数-代理IP
代理ip池
通过构建代理ip池可以让你编写的爬虫程序更加稳定
requests提供了一个代理ip参数proxies,该参数的语法结构如下
proxies={
'协议类型(http/https)':'协议类型://ip地址:端口号'
}
22.auth参数-用户认证
requests提供了一个auth参数,该参数的支持用户认证功能格式如下:
auth=('username','password')
23.Xpath表达式
Xpath即xml路径语言,它是一门在xml文档中查找信息的语言,Xpath使用路径表达式来选取xml/html文档中的节点或者节点集,python的第三方解析库lxml对Xpath路径表达式提供了良好的支持,能够解析xml与html文档
24.Xpath基本语法
表达式 | 描述 |
---|---|
node_name | 选取此节点的所有子节点 |
/ | 绝对路径匹配,从根节点选取 |
// | 相对路径匹配,从所有节点中查找当前选择的节点,包括子节点和后代节点 |
. | 选取当前节点 |
.. | 选取当前节点的父节点 |
@ | 选取属性值,通过属性值选取数据。常用元素属性有@id、@name、@type、@class、@title、@href |
25.Xpath通配符
通配符 | 描述 |
---|---|
* | 匹配任意元素节点 |
@* | 匹配任意属性节点 |
node() | 匹配任意类型的节点 |
26.Xpath内建函数
函数名称 | xpath表达式示例 | 示例说明 |
---|---|---|
text() | ./text() | 文本匹配,表示值当前节点中的文本内容 |
contains() | //div[contains(@id,'stu')]() | 模糊匹配,表示选择id中包含stu的所有div节点 |
last() | //*[@class='web'][last()] | 位置匹配,表示选择@class=‘web’的最后一个节点 |
position() | //*[@class='site'][position()<=2] | 位置匹配,表示选择@class=‘site’的前两个节点 |
start-with() | .//input[start-with(@id,'st)] | 匹配id以st开头的元素 |
ends-with() | .//input[endswith(@id,'st)] | 匹配id以st结尾的元素 |
27.lxml

注:不要使用跟库一样的命名,会报错
网友评论