爬虫介绍
-
定义:
- 爬虫即爬取数据
- 是用于请求网站并提取数据的自动化程序
-
本质:
- 爬虫的本质:模拟客户端向服务器发请求
- 所有能在APP(E.G、浏览器)上看到的数据都可以爬取。
- 爬虫的本质:模拟客户端向服务器发请求
-
注意事项:
- 控制爬虫的频次(即访问网站的速度)
- 不要将别人网站服务器搞崩
- 隐私数据不可爬取
- 《中华人民共和国个人信息保护法》的出台,侵犯公民个人信息应承担法律责任
- 不可将爬取的数据出售换钱
- 自觉遵守robots协议
- 本质上:robots协议是一个不成文的约定
- 【一般不遵守,否则也爬不到什么】
- 控制爬虫的频次(即访问网站的速度)
-
分类:
- 通用爬虫:【全部数据】
- 将整个页面数据全部保存到本地
- 聚焦爬虫:【部分数据】
- 从页面中仅提取出我们想要的数据
- 通用爬虫:【全部数据】
爬虫步骤【必记4步骤】
-
一、确定目标url
- url:统一资源定位符
- url组成部分:
- 协议 + 域名 + 路由(Path路径)
- 常用协议:
- http:超文本传输协议
- 端口:80
- 主要用于发布和接受HTML页面的方法
- https:超文本传输安全协议
- 端口:443
- 主要用于Web的安全传输协议,保障数据传输的安全性
- https:即在http上加入SSL/TLS协议,为数据传输提供了加密和身份验证。
- ssl安全套接层:对数据进行加密、保证数据传输的安全性。
- http:超文本传输协议
- 例如:https://www.runoob.com/python/python-tutorial.html
- 协议:https
- 域名:www.runoob.com
- 注意:一个域名对应一个IP地址,但一个IP地址不一定会有域名。
- 路由:python/python-tutorial.html
-
二、爬取(即发起请求、获取响应)
- 例如:【从用户角度看待“发起请求、获取相应”的过程】
- 客户端向服务器发起请求
- 发起请求:即在地址栏填入url,回车
- 服务器向客户端返回响应
- 返回响应:即服务器返回一个html页面
- 客户端向服务器发起请求
-
请求组成部分:request
- 请求方式 + 请求的url + 请求头 + 请求体
- http常用请求方式:
- get方式
- 参数显示在URL中
- get请求传参的参数:params
- post方式
- 参数在请求体中(即不在URL中)
- post请求传参的参数:data
- get方式
- 请求url:即上述目标url
- 请求头:(常用)
- Host:主机和端口号
- User-Agent:(简称UA)
- 浏览器自身的标识(即浏览器名称)
- Referer:可用来跟踪当前Web请求来自哪个页面,从哪个网站来的等(即页面跳转来源)
- Cookie:当前浏览网站服务器将少量数据储存到客户端的硬盘或内存,或是从客户端的硬盘读取数据的一种技术,可用于用户身份识别。
- Accept-Encoding:指出浏览器可接受的编码方式
- Accept-Charset:指出浏览器可接受的字符编码。
- 请求体:请求额外携带的数据
-
响应组成部分:response
- 响应状态(响应码) + 响应头 + 响应体
- 响应码:(表示请求成功失败与否)
- 200~299:【常用:200】
- 请求成功
- 300~399:页面跳转问题(重定向)
- 400~499:客户端出错
- 404:网址输入错误,服务器无法找到被请求的页面
- 403:权限不够,服务器拒绝客户端的访问
- 500~599:服务器端出错
- 200~299:【常用:200】
- 响应头:【一般不看】
- 由服务器返回的信息,所以不可完全相信。
- 响应体:
- 返回客户端请求资源的内容
- (例如:某网页的html源码)
- 例如:【从用户角度看待“发起请求、获取相应”的过程】
-
三、数据解析(即取出数据)
- JSON字符串解析
- HTML数据解析
- (详细分析如下)
-
四、存储数据
- (详细分析如下)
爬虫知识补充:
1、网页加载的方式
- 同步加载:
- 改变网址上的某些请求参数会导致整个网页发生改变
- 【例如:刷新页面、引起整个页面都进行刷新】
- 异步加载:【Fetch/XHR】
- 改变网址上的某些请求参数不会使整个网页发生改变
- 【即整体页面没有刷新(网址未改变),仅发生局部数据的更新】
- 例如:在百度搜索任意关键字,出现关联词对应的词语联想
2、反爬虫
- 反爬虫的原因:
- 不遵守规范的爬虫会影响网站的正常使用
- 某些网站上的数据是公司的重要资产
- 等等
- 概念:
- 爬虫:使用多种技术手段获取网站数据
- 反爬虫:阻止用户采用爬虫手段来获取自己网站的数据
- 反爬常用手段:
- 封IP
- 限制访问频率
- UA限制、cookie限制等
3、代理
- 作用:让服务器以为是不同的用户在发起请求
- 参数:
- 将键值对形式【键名key为协议名、值为 "协议名://IP:port" 】的代理值写在get方法(或post方法)的proxies参数中
- 补充:一般,伪装IP地址常常会采用代理服务器来实现。
- 一般而言,局域网中的多个内部设备共享同一个外网的公共IP地址,所以有时候封IP,也会是一个很不错的反爬手段。
- 代理服务器的作用:
- 代理服务器充当客户端与目标服务器之间的中间人,通过代理服务器发送请求,使得目标服务器无法直接获取到客户端的真实IP地址,从而实现客户端IP地址的伪装。
- 代理服务器既可隐藏客户端的真实IP地址,也可提供一定程度的匿名性和隐私保护。
- 免费的代理IP网站
- https://www.xiequ.cn/
- (里面的有些IP可能不能正常使用,但就免费而言、已经很不错了)
4、cookie
- 作用:(简而言之)cookie用于维持登陆状态
- 概念:
- 服务器给请求访问的浏览器一段数据(cookie),浏览器需将cookie保存在个人本地计算机上,在今后客户端向该服务器发起请求时,浏览器需携带这个数据。
- 【cookie由服务器端生成并发送到用户浏览器,然后浏览器会将Cookie存储在用户的计算机上。当用户再次访问相同的网站时,浏览器会将存储在计算机上的Cookie发送回服务器,从而使服务器能够识别用户并提供相应服务。】
- cookies由多个类似key=value形式组成。【常见】
- 每一个key=value的信息, 都代表用户的片段信息
- 多个key=value片段信息构成一个完整的cookies字段
- cookie传值的参数:
- 方法一:
- 将字典型或cookiejar对象形式的cookie写在get方法(或post方法)的cookies参数中
- 方法二:
- 将字符串形式的cookie写在headers参数中
- 方法一:
- 特点:
- cookie具有时效性
- cookie不安全
- 可以在不知道用户账号密码、仅用获取到的cookie,即可实现登录
5、session
- 作用:
- 在成功登录后,session可以自动带上cookie,而不需手动赋值cookie
- 存储位置:
- session保存在服务器中
- session通过在服务器端存储的记录信息来确定用户的合法身份
- cookie保存在客户端的浏览器中
- session保存在服务器中
- 使用:
- 1、先进行session的实例化
- import requests
- 即实例化变量名 = requests.session()
- 例如:sess1 = requests.session()
- 2、采用实例化变量(例如:sess1)发起get/post请求
- 例如如:login_respon = sess1.post(url=url1,data=data1,headers = header1,……)
- 1、先进行session的实例化
6、超时与异常处理
-
超时处理:timeout
- requests模块中get方法的timeout参数
- 语法:
- timeout(请求时间,响应时间)
- 例如:
- 请求超过3秒就报错
- req = requests.get(url=url1,timeout=3)
- 例如:
- 请求时间超过3秒、响应时间超过6秒就报错
- req = requests.get(url=url1,timeout=(3,6))
-
异常处理:try-except
- 捕捉所有异常
- try:
- 可能报错的代码块
- except Exception as err:
- print('报错原因',err)
- try:
- 精准捕捉某个异常
- 例如:对超时进行捕捉(E.G、谷歌在国内不能访问)
- try:
- 可能报错的代码块
- except requests.exceptions.ConnectTimeout as err:
- print('报错原因',err)
- try:
- 例如:对超时进行捕捉(E.G、谷歌在国内不能访问)
- 捕捉所有异常
-
7、列表的数据处理
- 【即从列表中获取特定元素的方法】
- 例如:取出列表第2条及之后的数据
- 方法一:切片
- list1 = list1[1: ]
- 方法二:pop函数
- 语法:pop( 待删除列表元素的索引 )
- list1.pop(0)
- 方法三:del函数
- 语法:del 列表名[ 待删除列表元素的索引 ]
- del list1[0]
- 方法一:切片
数据解析
目的:从爬取到的页面中提取出我们想要的数据。
1、数据内容分类
- 结构化数据:【即先有结构、后有数据】
- JSON数据【常见】
- XML文件(比较少见))
- 非结构化数据:【即先后数据、后有结构】
- HTML文件【常见】
2、JSON
- 定义:
- JSON是一种轻量级的数据交换格式,基于键值对的方式来组织数据。
- 作用:
- 可以实现前后端之间的数据交换
- 即JSON充当一种通用的桥梁,使得前端和后端之间可以方便地传递、解析数据。
- 也可在多种编程语言之间进行数据交换
- 即JSON是一种与语言无关的数据格式,可以被几乎所有的编程语言解析和生成JSON。
- 即使前端和后端采用不同的编程语言来实现,但它们之间仍然可以通过JSON进行数据交换。
- 例如:一个(由HTML、CSS、JS等编写的)前端和一个(由python编写的)后端
- 前端负责用户界面的设计与展示,后端负责数据处理和业务逻辑。
- 【即前端负责将用户输入的数据通过网络发送到后端,后端处理这些数据,并执行相应操作,最后将处理结果返回给前端并展示给用户。】
- 为实现前后端的数据交换、以及多种语言之间的数据交换:
- 因为不同编程语言有对应设定的不同数据类型,因此JSON字符串可以充当不同数据类型转换之间的 '中间人'
- 在前端:数据通常以JSON字符串形式发送到后端。
- 在后端:后端代码会接收并解析这些JSON字符串,并将其转换为Python中的数据类型,便于后续的数据处理、操作。
- 前端负责用户界面的设计与展示,后端负责数据处理和业务逻辑。
- 可以实现前后端之间的数据交换
-
JSON数据常用的处理方法
- 方法一、python中的json模块【推荐】
- 利用python中的json模块,转换为对应python格式进行键值对取值。
- 方法二、正则
- 方法三、jsonpath
- 方法一、python中的json模块【推荐】
-
Python中的json模块
- 作用:
- Python内置的json模块提供了处理JSON数据的多种函数方法。
- 功能包括序列化(将Python对象转换为JSON字符串)和反序列化(将JSON字符串转换为Python对象)。
- 常用函数(方法):
- json.dumps()
- 作用:将python数据类型转换成JSON字符串
- json.dump()
- 作用:将python数据类型转换成JSON格式的数据并写入文件
- 语法:json.dump(待转换的python数据,待写入文件的文件指针)
- 补充:dump()与dumps()的区别:
- dump()与dumps()方法类似
- 但dump()将转换成的JSON格式数据直接写入到指定文件中,而不是返回一个字符串。
- json.loads()
- 作用:将JSON字符串解析为python数据类型,便于后续在Python中进行的数据处理和操作。
- json.load()
- 作用:从文件中读取JSON格式的数据并解析为python数据类型。
- 补充:load()与loads()的区别:
- load()与loads()方法类似
- 但load()方法是从指定文件中读取JSON数据,而不是从JSON字符串中读取。
- 补充:dumps()、dump()函数中的参数:
- 【注意:load与loads函数不支持skipkeys、ensure_ascii参数】
- skipkeys=True:异常过滤、跳过报错
- 例如:在python中字典的键可以为元组,但JSON字符串不支持,所以在dumps()转化JSON字符串时会报错,忽略报错
- dict1 = {('name' , ‘age’): "peter", "age": 21}
- print(type(dict1)) # dict
- # dumps():将python数据类型 (键名含元组的dict)转换为JSON字符串(str),skipkeys=True:跳过异常报错
- json_dict1 = json.dumps(dict1, skipkeys=True)
- print(type(json_dict1)) # str
- 例如:在python中字典的键可以为元组,但JSON字符串不支持,所以在dumps()转化JSON字符串时会报错,忽略报错
- ensure_ascii=False:不对中文进行编码处理
- 例如:不对列表list1中的中文进行编码,使转换的JSON字符串中仍然能正常显示中文
- list1 = [1, 2, "皮蛋"]
- print(type(list1)) # list
- # dumps():将python数据类型(list)转换成JSON字符串(str)
- # ensure_ascii=False : 不进行中文编码处理
- jsonlist1 = json.dumps(list1, ensureascii=False)
- print(json_list1) # [1, 2, "皮蛋"]
- print(type(json_list1)) # str
- 补充:
- 在dump()与load()方法中的JSON文件中的数据以JSON字符串的形式表示。
- 当 (以JSON格式的) 数据被写入到文件中时,数据以 JSON字符串的形式表示。
- 当从文件中读取JSON数据时,load方法会将文件中的JSON字符串解析为相应的Python数据类型。
- 例如:
- with open( "文件名.json" , "r" , encoding="utf-8") as fp:
- filedata1 = fp.read() # 从JSON文件中读出数据
- print(type(filedata1)) # str
- 由此观之,JSON文件中的数据是以JSON字符串形式保存的
- with open( "文件名.json" , "r" , encoding="utf-8") as fp:
-
运用实例
- 例如:将list1列表中数据转换为JSON数据并写入到test.json文件中
- import json
- list1 = [1, 2, "皮蛋"]
- with open( "test.json" , "w" , encoding="utf-8") as fp:
- json.dump(dict1, fp , ensure_ascii=False)
- 例如:将JSON字符串(json_dict1)解析为对应的python数据类型
- import json
- list1 = [1, 2, "皮蛋"]
- print(type(list1)) # list
- jsonlist1 = json.dumps(list1, ensureascii=False, skipkeys=True)
- print(type(json_list1)) # str
- # loads():将将JSON字符串(json_dict1)对应的python数据类型(dict)
- pyjsonlist1 = json.loads(jsonlist1)
- print(type(py_jsonlist1)) # list
- 例如:将(test.json)文件中的JSON数据读出,并解析为对应的数据类型
- with open( "test.json" , "r" , encoding="utf-8" ) as fp:
- # 验证JSON文件中的数据类型
- filedata1 = fp.read()
- print(type(filedata1)) # str
- fp.seek(0) # 修改文件指针归零
- # 将test.json文件中的数据读出并解析为对应的数据类型
- filedata2 = json.load(fp)
- print(type(filedata2)) # list
- with open( "test.json" , "r" , encoding="utf-8" ) as fp:
- 例如:将list1列表中数据转换为JSON数据并写入到test.json文件中
- json.dumps()
- 作用:
3、HTML数据
-
HTML数据常用的处理方法
- xpath【推荐】
- 正则
- (BS4中)css选择器
-
BS4
- 定义:Beautiful Soup4【简称BS4】
- 一个可以从HTML或XML文件中提取数据的Python库
- 作用:可用于HTML数据或XML数据的解析
- Python标准库中的HTML解析器,用来解析HTML较为简单
- 支持CSS选择器
-
使用:
- cmd命令行中:安装BS包
- pip install beautifulSoup4
- pycharm中:导入BeautifulSoup库
- from bs4 import BeautifulSoup
- # 实例化
- soup = BeautifulSoup(待解析的HTML数据, 解析器)
- html.parser:【python自带的解析器】
- 例如:
- soup = BeautifulSoup( response.text , 'html.parser' )
- cmd命令行中:安装BS包
-
常用规则
- 【注意:下述的变量soup为实例化后对象】
- soup.标签名
- 获取文档中的第一个指定的HTML标签
- 获取标签属性
- soup.标签名.attrs
- 获取指定标签的所有属性
- soup.标签名.attrs['属性']
- 获取指定标签中的指定属性
- 补充:【标签属性的获取也可使用下述方法】
- 方法一:
- soup.标签名.get['属性']
- 方法二:省略attrs
- soup.标签名['属性']
- 方法一:
- soup.标签名.attrs
- 获取标签内容
- 方法一:string
- soup.标签名.string
- 前提条件:
- 标签中没有子标签或 (标签中仅有1个子标签但父标签中不能有内容),才可正确返回标签内容
- 方法二:get_text()
- soup.标签名.get_text()
- 返回一个标签中的所有文本内容,包括其子孙节点的内容
- 方法三:text
- soup.标签名.text 【常用】
- 方法一:string
- 查找指定标签
- soup.find_all()
- 语法:soup.find_all( '标签名x' )
- 查找所有标签x
- 语法:soup.find_all( '标签名y' , 属性/类名搜索 )
- 通过属性/类名来查找指定的标签y
- 语法:soup.find_all( '标签名x' )
- 注意:通过CSS的类名搜索时,需要使用 class_ 参数
- 因为class为python中的关键字
- soup.find_all()
- soup.select('css选择器')
- 匹配所有符合条件的数据
- 返回列表
- soup.select_one('css选择器')
- 匹配所有符合条件的第一条数据
- 补充:
- 在HTML中,一个标签可以有多个class类名,用于同时应用多个样式;但每个标签只能有一个唯一的id名,用于标识该元素在文档中的唯一位置。
- 一个HTML元素可具有多个class类名
- 多类名的方式允许为同一个元素定义多个样式类,并通过CSS同时应用这些样式
- 一个HTML元素只能有一个唯一的id名
- 每个HTML元素在文档中是唯一的,用于标识该元素在文档中的唯一位置。
- 定义:Beautiful Soup4【简称BS4】
-
CSS选择器
- 作用:用于选择HTML元素
- 分类:
- 标签选择器
- 通过标签名来选择HTML元素
- 类选择器
- 【类选择器以 . 类名 开头】
- id选择器
- 【id选择器以 #id名 开头】
- 后代选择器
- 【使用空格来连接多个选择器】
- 选择指定元素下的所有后代元素,包括直接后代和间接后代
- 即选择指定元素的所有子孙元素
- 子元素选择器
- 【使用大于号来连接多个选择器】
- 选择指定元素的直接子元素,不包括孙子元素及更远的后代元素
- 相邻兄弟选择器
- 选择指定元素相邻兄弟关系的HTML元素
- 例如:
- h2+p选择器:选择紧接在<h2>元素后的<p>元素
- 标签选择器
-
lxml
- 定义:
- lxml是一个HTML/XML文件的解析器
- 一个可以从HTML或XML文件中提取数据的Python库
-
作用:
- 【同BS4】可用于HTML数据或XML数据的解析
- lxml为局部遍历,(而BS4会载入整个文档,解析整个DOM树)
- 因此BS4的时间和内存开销大,所以性能低于lxml。
-
使用:
- cmd命令行中:安装lxml包
- pip install lxml
- 【补充:若下载速度过慢(或报错),可尝试采用下述(-i)换源】
- pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple
- pycharm中:导入lxml库
- from lxml import etree
- # 实例化:将带解析数据转化为element对象
- # etree.HTML(待解析的HTML数据)
- tree = etree.HTML( 待解析的HTML数据 ) # 变量名tree为实例化element对象
- # etree.tostring( 实例化element对象 ) # 将实例化element对象转换为字符串
- tree_str = etree.tostring(tree)
- cmd命令行中:安装lxml包
-
XPath语法:
- 实例化element对象. xpath( 'xpath规则' )
- 函数方法xpath():返回列表
-
XPath常用规则(Xpath常用的定位方法)
- 【注意:XPath规则的写法很多,只要能获取到数据即可】
- 相对定位://
- 从当前节点选取子孙节点
- [ 功能同CSS选择器中的后代选择器 ]
- 绝对定位:/
- 从当前节点选取直接子节点
- [ 功能同CSS选择器中的子代选择器 ]
- 条件筛选:[]
- 索引取值:
- 例如:(在tr标签下包裹着5个td标签)获取tr标签下的第2个td标签的xpath规则
- //tr/td[2]
- 例如:(在tr标签下包裹着5个td标签)获取tr标签下的第2个td标签的xpath规则
- last方法:last()
- 作用:当存在多个相同标签时,可使用last()方法,定位到最后一个标签
- 例如:定位到最后一个li标签的XPath规则
- //li[last()]
- 例如:定位到倒数第二个li标签的XPath规则
- 在last()后面加上-1,代表倒数第二个
- //li[last()-1]
- 例如:定位到第一个li标签的XPath规则
- XPath中的索引从1开始(而不是0)
- //li[1]
- 属性查找:@
- 用途一:获取某标签下的指定属性
- //标签名/@属性名
- 例如:获取所有li标签的class属性
- //li/@class
- 用途二:定位到指定属性下的标签
- //标签名[@属性名='属性值']
- 例如:定位到id值为kw的input标签
- //input[@id="kw"]
- 例如:定位href属性为link3.html的a标签
- //a[@href="link3.html"]
- 用途一:获取某标签下的指定属性
- text方法:text()
- 作用:获取标签内容
- 例如:获取li标签子孙节点的内容
- //li//text()
- 通配符:*
- 作用:匹配任何元素节点(标签)
- 例如:匹配有class属性的所有标签
- //*[@class]
- 操作符:|
- 作用:用于将多个XPath规则组合在一起,使之同时匹配多个节点。
- 用'|'将多个XPath规则分隔开,使每个XPath规则互不干扰。
- 例如:匹配具有class属性为'example'的div元素以及id属性为'test'的span元素。
- //div[@class='example'] | //span[@id='test']
- 作用:用于将多个XPath规则组合在一起,使之同时匹配多个节点。
- 选取当前节点:.
- 注意:循环中的xpath规则前第一个写(点) . 表示为当前标签结点
- 例如:
- . //标签名(xpath规则)
- 选取当前节点的父节点:..
- 补充:child : : *
- 例如:获取定位到id值为kw的input标签下的所有子标签对象
- //input[@id="kw"]/child::*
- 例如:获取定位到id值为kw的input标签下的所有子标签对象
- 定义:
4、正则
-
作用:
- 通过正则表达式匹配想要的数据
- 元字符:【即组成正则表达式的基本元素】
- . :匹配任意字符(换行符除外)
- * :匹配0个或者多个
- + :匹配一个或者多个
- ? :匹配0个或一个
- \s:匹配空白字符(空格,tab,换行符等)
- \d:匹配数字(0~9)
- \D:匹配非数字
- 等等
-
贪婪与非贪婪模式
- 贪婪模式:在表达式匹配成功的前提下,尽可能的多匹配。
- 例如:.*
- 非贪婪模式:在表达式匹配成功的前提下,尽可能的少匹配。
- 例如:.*?或.+?
- 补充:
- 数量词:*(匹配0个或者多个)、+(匹配一个或者多个)等
- 在python中,数量词默认为贪婪模式
- 在数量词后面跟 ?表示非贪婪模式
- 贪婪模式:在表达式匹配成功的前提下,尽可能的多匹配。
-
re模块
- Python中内置的正则表达式模块
- 常用函数(方法)
- re.findall()
- 语法:re.findall(正则规则,待匹配的原始字符串)
- 作用:查找所有匹配的结果,并返回列表。
- re.sub()
- 语法:re.sub(正则规则,待替换的内容,待匹配的原始字符串)
- 作用:用于替换原始字符串中的匹配项
- 适用于:
- 文件保存时,文件名中不允许有非法字符,此时可用sub替换函数
- re.findall()
- 常用参数
- re.S参数:
- (支持多行匹配)匹配包括 '换行' 在内的所有字符
- 适于"""多行字符串"""
- 【若不使用re.S参数,则仅在每一行内进行匹配,若该行没有匹配成功,则从下一行开始重新按正则表达式匹配。】
- (支持多行匹配)匹配包括 '换行' 在内的所有字符
- re.I参数
- 匹配不区分大小写
- re.S参数:
-
常用正则表达式
- 1、.*?
- 匹配任意数量的重复,但为非贪婪模式。
- (在能使整个匹配成功的前提下使用最少的重复。)
- 2、(.*?)
- 同上述正则规则.*?,但只返回括号()中匹配到的内容。
- 3、匹配中文:[\u4e00-\u9fa5]
- 中文的Unicode编码范围主要在[u4e00-u9fa5]
- 但范围不太完整,例如没有全角标点【但基本够用】
- 例如:匹配字符串str1中的中文
- str1 = '卫1星a俯?瞰c祖:国\南1/北*春<耕>好|风光'
- str_result = re.findall('[\u4e00-\u9fa5]',str1)
- print(str_result)
- 中文的Unicode编码范围主要在[u4e00-u9fa5]
- 4、匹配非法字符:[\\/:*?\"<>|]
- 例如:将字符串str1中的非法字符替换为空
- str1 = '卫1星a俯?瞰c祖:国\南1/北*春<耕>好|风光'
- str_result = re.sub( "[\\/:*?\"<>|]" , '' , str1 )
- print(str_result)
- 例如:将字符串str1中的非法字符替换为空
- 1、.*?
-
补充:正则表达式--中文的提取
- 代码:
- import re
- # 使用正则表达式匹配中文
- data = " 各种混合着中文的数据 "
- chinese_pattern = re.compile(r'[\u4e00-\u9fa5]+')
- matches = chinese_pattern.findall(data)
- print(matches) # 以列表形式输出匹配到的中文
- 注解:
- re.compile(r'[\u4e00-\u9fa5]+'):
- re.compile()函数:将字符串形式的正则表达式编译成一个可重复使用的正则对象。
- r:告诉Python解释器,不转义字符串中的特殊字符
- 文件路径前面加上'r' 避免转义
- [\u4e00-\u9fa5]+:
- 此正则表达式可以匹配一个或多个连续的汉字字符。
- [\u4e00-\u9fa5]:为一个字符集合,包含Unicode中所有汉字的范围
- \u4e00:是第一个汉字的Unicode编码
- \u9fa5:是最后一个汉字的Unicode编码
- +:表示匹配前面字符集合中的字符一次或多次
- chinese_pattern.findall(data):返回一个列表
- 其中包含在data字符串中找到的所有中文字符的匹配项。
- 语法:
- "正则表达式". findall(字符串)
- findall():正则表达式对象的方法,用于在字符串中查找所有匹配的子串,并以列表的形式返回所有匹配结果。
- re.compile(r'[\u4e00-\u9fa5]+'):
- 代码:
-
补充:中文Unicode编码的解码
- 若爬取数据的中文为Unicode编码,要想使中文正常显示,可对其进行Unicode解码
- 【默认以'utf-8'编码,以指定的'unicode_escape'解码】
- 'Unicode字符'.encode().decode('unicode_escape')
- 若爬取数据的中文为Unicode编码,要想使中文正常显示,可对其进行Unicode解码
数据解析--小结
- 文本内容数据
- 结构化数据:
- 例如:JSON数据
- JSON数据解析常用方法:
- python中json模块【将JSON数据转为python数据类型进行键值对取值(推荐)】
- 正则
- 非结构数据:
- 例如:HTML文件
- HTML数据解析常用方法:
- XPath(推荐)
- BS4中CSS选择器
- 正则
- 结构化数据:
- 不同类型的数据,需要采用不同的方式来处理。
- 强烈推荐:
- 遇到JSON字符串,采用python中json模块来处理。
- 遇到HTML文件,采用XPath来处理。
- 强烈推荐:
数据存储
-
常见的数据存储格式
- 文本文件
- 例如:txt、json、csv等
- Excel表格
- MySQL数据库
- 文本文件
-
(常用)数据的存储方法
- 方法一、open()函数
- 作用:通过open函数将爬取的数据写入文件中
- 语法:
- open('文件名', '文件打开方式' , encoding='编码方式' )
- 文件打开方式
- r:只读(若文件不存在,则报错)
- w:只写(若文件不存在,则自动新建)
- 注意:是自动创建文件,而不是文件夹(目录)
- a:在文件末尾追加数据
- rb,wb,ab:操作二进制
- 补充:图片、音频和视频文件通常以二进制形式存储。
- r+:读写
- 常用的编码方式:utf-8
- 方法二、存储到excel表格
- 1、编写Python代码
- 例如:Excel模板代码【哈哈哈,私我才发您】
- 2、pandas库【常见且高效的方法】
- 1、编写Python代码
- 方法三、存储到MySQL数据库
- Python的pymysql库
- 方法一、open()函数
-
pymysql
-
定义:
- 是python用于连接和操作MySQL数据库的模块。
- 是python3.x版本用来操作MySQL数据库的一个模块。
-
作用:
- 在Python程序中执行对数据库的各种操作(例如:查询、插入、更新和删除数据等)
-
使用:
- cmd命令行中:安装pymysql库
- pip install pymysql
- 【补充:若下载速度过慢(或报错),可尝试采用下述(-i)换源】
- pip install lxml -i https://pypi.tuna.tsinghua.edu.cn/simple
- pycharm中:
- import pymysql # 导入pymysql模块
- # 创建数据库连接
- 数据库连接成功后,返回一个成功连接的对象
- conn = pymysql.connect(
- host="主机名或IP地址",
- port=3306,
- user="用户名",
- password="密码",
- db="待操作的数据库名")
- 创建游标对象:用于执行SQL查询操作、执行指定的SQL语句
- cursor = conn.cursor()
- 执行查询操作
- 例如:查询指定表下的所有数据
- select_sql = "SELECT * FROM 表名"
- cursor.execute(select_sql)
- 查询表中的数据
- print(cursor.fetchall())
- 执行插入操作(即数据的写入)
- 【注意:需要表先存在,才可往表中写入数据】
- insert_sql = "插入语句"
- cursor.execute(insert_sql)
- conn.commit() # 确认提交(将当前操作所有更改提交到数据库)
- roback():回滚(即返回上一步操作的结果)
- 关闭游标和连接
- cursor.close() # 关闭游标
- conn.close() # 关闭连接
- cmd命令行中:安装pymysql库
-