Python模块之re模块、第三方包、openpyxl模块

re模块

在python中如果想要使用正则表达式,re模块是选择之一

re 模块使 Python 语言拥有全部的正则表达式功能。

findall

在字符串中找到正则表达式所匹配的所有子串,并返回一个列表,如果有多个匹配模式,则返回元组列表,如果没有找到匹配的,则返回空列表。

ps:findall通过正则表达式筛选出文本中所有符合条件的数据,match 和 search 是匹配一次 findall 匹配所有

# 语法格式
re.findall(pattern, string, flags=0)
或
pattern.findall(string[, pos[, endpos]])

参数:

  • pattern 匹配模式(正则表达式)。
  • flags 标志位,用于控制正则表达式的匹配方式
  • string 待匹配的字符串。
  • pos 可选参数,指定字符串的起始位置,默认为 0。
  • endpos 可选参数,指定字符串的结束位置,默认为字符串的长度。

>>> import re
# 查找字符串中所有a
>>> res = re.findall('a', 'kwan oscar aaa')  # 返回所有满足匹配条件的结果,放在列表里
>>> res
['a', 'a', 'a', 'a', 'a']

# 多个匹配模式,返回元组列表:
>>> res = re.findall(r'(\w+)=(\d+)', 'set width=20 and height=10')
>>> res
[('width', '20'), ('height', '10')]

re.finditer

和 findall 类似,在字符串中找到正则表达式所匹配的所有子串,并把它们作为一个迭代器返回, 节省内存。

# 语法格式
re.finditer(pattern, string, flags=0)

>>> import re
>>> res = re.finditer('a', 'kwan oscar aaa')
>>> res
<callable_iterator object at 0x0000025941F3FA30>

re.match 和 re.search

  • re.match 尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,match()就返回none。
  • re.search 扫描整个字符串并返回第一个成功的匹配。
# 语法格式
re.match(pattern, string, flags=0)
re.search(pattern, string, flags=0)

匹配成功re.match、re.search方法都会返回一个匹配的对象,否则返回None。

我们可以使用group(num) 或 groups() 匹配对象函数来获取匹配表达式。

匹配对象方法 描述
group(num=0) 匹配的整个表达式的字符串,group() 可以一次输入多个组号,在这种情况下它将返回一个包含那些组所对应值的元组。
groups() 返回一个包含所有小组字符串的元组,从 1 到 所含的小组号。
>>> import re

# 不在起始位置匹配
>>> res = re.match('a', 'kwan oscar aaa')  # re.match
>>> print(res)
None

>>> res = re.search('a', 'kwan oscar aaa')  # re.search
>>> print(res)
<re.Match object; span=(2, 3), match='a'>

# 在起始位置匹配
>>> res = re.match('a', 'aaa kwan oscar')  # re.match
>>> print(res)
<re.Match object; span=(0, 1), match='a'>

>>> res = re.search('a', 'aaa kwan oscar')  # re.search
>>> print(res)
<re.Match object; span=(0, 1), match='a'>

>>> print(res.group())  # group(),两者都是返回 a
a

 # group()
>>> import re
>>>
>>> line = "Cats are smarter than dogs"
>>> # .* 表示任意匹配除换行符(\n、\r)之外的任何单个或多个字符
>>> # (.*?) 表示"非贪婪"模式,只保存第一个匹配到的子串
>>> matchObj = re.match( r'(.*) are (.*?) .*', line, re.M|re.I)  # match/search group()结果一样
>>>
>>> if matchObj:
...    print ("matchObj.group() : ", matchObj.group())
...    print ("matchObj.group(1) : ", matchObj.group(1))
...    print ("matchObj.group(2) : ", matchObj.group(2))
... else:
...    print ("No match!!")
...
matchObj.group() :  Cats are smarter than dogs
matchObj.group(1) :  Cats
matchObj.group(2) :  smarter

re.match与re.search的区别

re.match 只匹配字符串的开始,如果字符串开始不符合正则表达式,则匹配失败,函数返回 None,而 re.search 匹配整个字符串,直到找到一个匹配。

>>> import re
>>>
>>> line = "Cats are smarter than dogs"
>>>
>>> matchObj = re.match( r'dogs', line, re.M|re.I)  # re.match
>>> if matchObj:
...    print ("match --> matchObj.group() : ", matchObj.group())
... else:
...    print ("No match!!")
...
No match!!
>>>
>>> matchObj = re.search( r'dogs', line, re.M|re.I)  # re.search
>>> if matchObj:
...    print ("search --> matchObj.group() : ", matchObj.group())
... else:
...    print ("No match!!")
...
search --> matchObj.group() :  dogs

compile 函数

compile 函数用于编译正则表达式,生成一个正则表达式( Pattern )对象,供 match() 和 search() 这两个函数使用。可以反复使用,减少代码冗余。

# 语法格式
re.compile(pattern[, flags])

参数:

  • pattern : 一个字符串形式的正则表达式

  • flags 可选,表示匹配模式,比如忽略大小写,多行模式等,具体参数为:

    • re.I 忽略大小写

    • re.L 表示特殊字符集 \w, \W, \b, \B, \s, \S 依赖于当前环境

    • re.M 多行模式
    • re.S 即为' . '并且包括换行符在内的任意字符(' . '不包括换行符)
    • re.U 表示特殊字符集 \w, \W, \b, \B, \d, \D, \s, \S 依赖于 Unicode 字符属性数据库
    • re.X 为了增加可读性,忽略空格和' # '后面的注释
>>> import re

>>> obj = re.compile('a')
>>> print(re.findall(obj,'sdsd14dasd2167dafg'))
['a', 'a']
>>> print(re.findall(obj,'fssd45adscxaazxczx'))
['a', 'a', 'a']
>>> print(re.findall(obj,'dadadafdsadaasfffd'))
['a', 'a', 'a', 'a', 'a', 'a']


>>> pattern = re.compile(r'\d+')                    # 用于匹配至少一个数字
>>> m = pattern.match('one12twothree34four')        # 查找头部,没有匹配
>>> print( m )
None
>>> m = pattern.match('one12twothree34four', 2, 10) # 从'e'的位置开始匹配,没有匹配
>>> print( m )
None
>>> m = pattern.match('one12twothree34four', 3, 10) # 从'1'的位置开始匹配,正好匹配
>>> print( m )                                        # 返回一个 Match 对象
<_sre.SRE_Match object at 0x10a42aac0>
>>> m.group(0)   # 可省略 0
'12'
>>> m.start(0)   # 可省略 0
3
>>> m.end(0)     # 可省略 0
5
>>> m.span(0)    # 可省略 0
(3, 5)

当匹配成功时返回一个 Match 对象,其中:

  • group([group1, …]) 方法用于获得一个或多个分组匹配的字符串,当要获得整个匹配的子串时,可直接使用 group()group(0)
  • start([group]) 方法用于获取分组匹配的子串在整个字符串中的起始位置(子串第一个字符的索引),参数默认值为 0;
  • end([group]) 方法用于获取分组匹配的子串在整个字符串中的结束位置(子串最后一个字符的索引+1),参数默认值为 0;
  • span([group]) 方法返回 (start(group), end(group))

re模块补充说明

分组

>>> res = re.findall('adb', 'asadbaadbfabddsadb')
>>> print(res)
['adb', 'adb', 'adb']
>>>
>>> res = re.findall('a(d)b', 'asadbaadbfabddsadb')
>>> print(res)      # 这是因为findall会 优先 把匹配结果组里内容返回,如果想要匹配结果,取消权限即可
['d', 'd', 'd']
>>>
>>> res = re.findall('a(?:d)b', 'asadbaadbfabddsadb')  # 取消分组优先展示 (?:)
>>> print(res)
['adb', 'adb', 'adb']

别名

>>> import re
>>> ret = re.search("<(?P<tag_name>\w+)>\w+</(?P=tag_name)>", "<h1>hello</h1>")
# 还可以在分组中利用?<name>的形式给分组起名字
# 获取的匹配结果可以直接用group('名字')拿到对应的值
>>> print(ret.group('tag_name'))
h1
>>> print(ret.group())
<h1>hello</h1>

>>> ret = re.search(r"<(\w+)>\w+</\1>", "<h1>hello</h1>")
>>> # 如果不给组起名字,也可以用\序号来找到对应的组,表示要找的内容和前面的组内容一致
>>> # 获取的匹配结果可以直接用group(序号)拿到对应的值
>>> print(ret.group(1))
h1
>>> print(ret.group())
<h1>hello</h1>

第三方模块下载

  1. 第三方模块必须先下载才可以导入使用
  2. python下载第三方模块需要借助于pip工具
  3. 下载命令
    pip3 install 模块名

pip安装

通过以下命令来判断是否已安装:

pip --version     # Python2.x 版本命令
pip3 --version    # Python3.x 版本命令

如果你还未安装,则可以使用以下方法来安装:

$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py   # 下载安装脚本
$ sudo python get-pip.py    # 运行安装脚本

注意:用哪个版本的 Python 运行安装脚本,pip 就被关联到哪个版本,如果是 Python3 则执行以下命令:

$ sudo python3 get-pip.py    # 运行安装脚本。

一般情况 pip 对应的是 Python 2.7,pip3 对应的是 Python 3.x。

注意事项

如果 Python2 和 Python3 同时有 pip,则使用方法如下:

Python2:

python2 -m pip install XXX

Python3:

python3 -m pip install XXX

下载速度慢的问题

pip工具默认是从国外的仓库地址下载模块,速度很慢时可以使用国内镜像下载(源地址)

清华大学 :https://pypi.tuna.tsinghua.edu.cn/simple/

阿里云:http://mirrors.aliyun.com/pypi/simple/

中国科学技术大学 :http://pypi.mirrors.ustc.edu.cn/simple/

华中科技大学:http://pypi.hustunique.com/

豆瓣源:http://pypi.douban.com/simple/

腾讯源:http://mirrors.cloud.tencent.com/pypi/simple

华为镜像源:https://repo.huaweicloud.com/repository/pypi/simple/

临时使用:

pip install -i 包名 https://pypi.tuna.tsinghua.edu.cn/simple

例如,安装 Django:

pip install -i Django https://pypi.tuna.tsinghua.edu.cn/simple

网络爬虫

  1. 什么是互联网

    将全世界的计算机连接到一起组成的网络

  2. 互联网发明的目的是什么

    将接入互联网的计算机上面的数据彼此共享

  3. 上网的本质是什么

    基于互联网访问别人计算机上面的资源(有些计算机存在的意义就是让别人访问,这种类型的计算机我们也称之为服务器)

  4. 网络爬虫的本质

    模拟计算机浏览器朝目标网址发送请求回去数据并筛选

    ​ 只要是浏览器可以访问到的数据网络爬虫理论上都可以

爬取公司信息

requests 方法

requests 方法如下表:

方法 描述
delete(url, args) 发送 DELETE 请求到指定 url
get(url, params, args) 发送 GET 请求到指定 url
head(url, args) 发送 HEAD 请求到指定 url
patch(url, data, args) 发送 PATCH 请求到指定 url
post(url, data, json, args) 发送 POST 请求到指定 url
put(url, data, args) 发送 PUT 请求到指定 url
request(method, url, args) 向指定的 url 发送指定的请求方法

每次调用 requests 请求之后,会返回一个 response 对象,该对象包含了具体的响应信息。

import requests

# 朝目标地址发送网络请求获取响应数据(相当于在浏览器地址栏中输入网址并回车)
res = requests.get('http://www.redbull.com.cn/about/branch')
print(res.content)  # 获取bytes类型的数据
print(res.text)  # 获取解码之后的数据
# 为了避免每次执行程序都要发送网络请求  也可以提前保存页面数据到文件
with open(r'hn.html','wb') as f:
    f.write(res.content)

import re

# 读取页面数据
with open(r'hn.html', 'r', encoding='utf8') as f:
    data = f.read()
# 研究目标数据的特征 编写正则筛选
# 1.获取所有的分公司名称
company_name_list = re.findall('<h2>(.*?)</h2>', data)
# print(res)
# 2.获取所有的分公司地址
company_addr_list = re.findall("<p class='mapIco'>(.*?)</p>", data)
# print(company_addr_list)
# 3.获取所有的分公司邮箱
company_email_list = re.findall("<p class='mailIco'>(.*?)</p>", data)
# print(company_email_list)
# 4.获取所有的分公司电话
company_phone_list = re.findall("<p class='telIco'>(.*?)</p>", data)
# print(company_phone_list)
# 5.将上述四个列表中的数据按照位置整合
res = zip(company_name_list, company_addr_list, company_email_list, company_phone_list)
# 6.处理数据(展示 保存 excel)
for i in res:  # ('红牛杭州分公司', '杭州市上城区庆春路29号远洋大厦11楼A座', '310009', '0571-87045279/7792')
    print("""
    公司名称:%s
    公司地址:%s
    公司邮箱:%s
    公司电话:%s
    """ % i)

openpyxl模块

  • openpyxl 是个读写 Excel 2010 xlsx/xlsm/xltx/xltm 的 Python 库,简单易用,功能广泛,单元格格式/图片/表格/公式/筛选/批注/文件保护等等功能应有尽有,图表功能是其一大亮点

  • OpenPyXl 几乎可以实现所有的 Excel 功能,主要用于操作excel表格,也是pandas底层操作表格的模块

excel版本问题

​ 03版本之前 excel文件的后缀名 .xls

​ 03版本之后 excel文件的后缀名 .xlsx

​ 如果是苹果电脑excel文件的后缀 .csv

安装

用 pip 安装

pip3 install openpyxl

openpyxl实操

# 1.创建excel文件
from openpyxl import Workbook  # 导入模块

wb = Workbook()  # 创建excel文件

wb1 = wb.create_sheet('成绩表')
wb2 = wb.create_sheet('财务表')
wb3 = wb.create_sheet('校花表', 0)

wb1.title = '开黑表'  # 支持二次修改
wb1.sheet_properties.tabColor = "1072BA"  # 修改工作簿颜色

wb.save(r'kk.xlsx')  # 保存文件

# 2.写入数据
# 第一种写入方式
wb1['A1'] = '???'
wb1['B2'] = 'DDD'
# 第二种写入方式
wb1.cell(row=3, column=3, value='你瞅啥')
# 第三种写入方式(批量写入)
wb1.append(['username', 'password', 'age', 'gender', 'hobby'])
wb1.append(['kwan1', 123, 18, 'female', 'read'])
wb1.append(['kwan2', 123, 18, 'female', 'read'])
wb1.append(['kwan3', 123, 18, 'female', 'read'])
wb1.append(['kwan4', 123, 18, 'female', 'read'])
wb1.append(['kwan4', 123, 18, 'female', None])
wb1.append([None, 123, 18, 'female', ''])

wb1['F11'] = '=sum(B5:B10)'   # 计算单元格B5到B10的和
wb.save(r'111.xlsx')  # 保存文件

作业

import requests
import re
from openpyxl import Workbook

# 朝目标地址发送网络请求获取响应数据(相当于在浏览器地址栏中输入网址并回车)
res = requests.get('http://www.redbull.com.cn/about/branch')
# 为了避免每次执行程序都要发送网络请求  也可以提前保存页面数据到文件
with open(r'hn.html', 'wb') as f:
    f.write(res.content)

# 读取页面数据
with open(r'hn.html', 'r', encoding='utf8') as f:
    data = f.read()
# 研究目标数据的特征 编写正则筛选
# 获取所有的分公司名称
company_name_list = re.findall('<h2>(.*?)</h2>', data)
# 获取所有的分公司地址
company_addr_list = re.findall("<p class='mapIco'>(.*?)</p>", data)
# 获取所有的分公司邮箱
company_email_list = re.findall("<p class='mailIco'>(.*?)</p>", data)
# 获取所有的分公司电话
company_phone_list = re.findall("<p class='telIco'>(.*?)</p>", data)
# 将上述四个列表中的数据按照位置整合
res = zip(company_name_list, company_addr_list, company_email_list, company_phone_list)
# 创建excel文件
wb = Workbook()
# 创建一个sheet
ws = wb.create_sheet("hn_sheet")
# 填入数据
ws.append(['分公司名称', '分公司地址', '分公司邮箱', '分公司电话'])
for i in res:
    ws.append(i)
# 保存文件
wb.save(r'hn.xlsx')

posted @ 2022-07-20 20:52  梦想有双休  阅读(253)  评论(0)    收藏  举报