因区域平台电子病例解析采用的是Oracle连接,不管是原始数据库还是解析后的存储数据库均为Oracle数据库,因为需要配置相应的Oracle连接。即配置Oracle数据库的IP,实例,用户,密码等等。
如下:oracleDb_get为区域平台电子病例来源地址相应配置。
[oracleDb_get]
host = *********** #服务器IP
port = 1521 #数据库端口号
user = ******** #用户
password = ******************** #密码
dbname = ****** #实例
如下:oracleDb_save为区域平台电子病例解析后存储地址相应配置。
[oracleDb_save]
host = ***********
port = 1521
user = ********
password = ********************
dbname = ******
因互联互通平台电子病例解析采用的是Sql Server连接,不管是原始数据库还是解析后的存储数据库均为Sql Server数据库,因为需要配置相应的Sql Server连接。即配置Sql Server数据库的IP,实例,用户,密码等等。
如下:Db_get为人民医院互联互通平台电子病例来源地址相应配置。
[Db_get]
host = ************ #服务器IP
port = 1433 #数据库端口号
user = *********** #用户
password = ********** #密码
dbname = ******* #实例
如下:Db_save为人民医院互联互通平台电子病例解析后存储地址相应配置。
[db_save]
host = ************
port = 1433
user = ***********
password = **********
dbname = *******
def get_db_url():
'''
获取sql server数据库的实例,用户,密码,端口号,功能:获取取数用户
:return:
'''
cf = ConfigParser()
cf.read('D:/PytionDate/emrStruct4/conf/app.conf')#app.conf文件存放路径
dbHost = cf.get("db_get", "host")
dbPort = cf.get("db_get", "port")
dbUser = cf.get("db_get", "user")
dbPassword = cf.get("db_get", "password")
dbName = cf.get("db_get", "dbName")
db_url = "mssql+pymssql://"+dbUser+":"+dbPassword+"@"+dbHost+":"+dbPort+"/"+dbName
return db_url
def get_db_url2():
'''
获取oracle数据库的实例,用户,密码,端口号,功能:获取取数用户
:return:
'''
cf = ConfigParser()
# cf.read(sys.path[0] + "/conf/app.conf")
cf.read('D:/PytionDate/emrStruct4/conf/app.conf')
dbHost = cf.get("oracleDb_get", "host")
dbPort = cf.get("oracleDb_get", "port")
dbUser = cf.get("oracleDb_get", "user")
dbPassword = cf.get("oracleDb_get", "password")
dbName = cf.get("oracleDb_get", "dbName")
db_url = dbUser + "/" + dbPassword + "@" + dbHost + ":" + dbPort + "/" + dbName
return db_url
conn = create_engine(
get_db_url() #调用上述的def get_db_url()函数获取Sql Server的URL地址
, max_overflow=0, # 超过连接池大小外最多创建的连接数
pool_size=5, # 连接池大小
pool_timeout=30, # 连接池中没有线程最多等待时间,否则报错
pool_recycle=-1 # 多久之后对连接池中的连接进行回收(重置)-1不回收
, echo=True
, encoding='utf-8'
, convert_unicode=True
)
# 每次执行数据库操作的时候,都需要创建一个session,相当于管理器(相当于Django的ORM的objects)
session_factory = sessionmaker(bind=conn)
# 线程安全,基于本地线程实现每个线程用同一个session
Session = scoped_session(session_factory)
# 实例化(相当于实现了一个单例模式)
session = Session()
Base = declarative_base()
# declarative_base()是一个工厂函数,它为声明性类定义构造基类。init 在继承了Base。隶属sqlalchemy模块之下
url_get = get_db_url2()
#调用上述的def get_db_url2()函数获取Oracler的URL地址
db = oracle.connect(url_get)
#python连接Oracler数据库
#编写sql语句从原始数据库中查询出所需数据(注意:需求不同,sql语句也不同)
sql = "select y.KSSJ, m.BRID, m.MZHM, m.BRXM, m.jtdh lxdh, w.JLXH jlxh, w.BRTGJC DLNR, '' BLBH, w.JZXH jzxh from bshrp.dbo.MS_BRDA m \
inner join bshrp.dbo.YS_MZ_JZLS y on y.brbh=m.brid \
inner join bshrp.dbo.OMR_BLZY w on w.jzxh=y.jzxh \
where M.ZXBZ<>1 \
and (w.BRTGJC like '%℃%' or w.BRTGJC like '%度%' or w.BRTGJC like '%T%' or\ w.BRTGJC like '%°%' or w.BRTGJC like '%mmHg%' \
or w.BRTGJC like '%分%' or w.BRTGJC like '%次%' or w.BRTGJC like '%P%' or \ w.BRTGJC like '%R%' or w.BRTGJC like '%p%' or w.BRTGJC like '%r%') \
and y.KSSJ >= to_date('{0}', 'yyyy-MM-dd hh24:mi:ss') and y.KSSJ < \ to_date('{1}', 'yyyy-MM-dd hh24:mi:ss') \
order by y.KSSJ , w.JLXH ".format(str(d1), str(d2))
sj = session.execute(sql).fetchall()
#调用上述步骤2的session对象连接sql server库,即主功能:mysql查
#编写sql语句从原始数据库中查询出所需数据(注意:需求不同,sql语句也不同)
sql_bj = "select y.KSSJ, m.BRID, m.MZHM, m.BRXM, m.jtdh lxdh, w.JLXH jlxh, w.BRTGJC DLNR, '' BLBH, w.JZXH jzxh from his_bj_hc.MS_BRDA m \
inner join his_bj_hc.YS_MZ_JZLS y on y.brbh=m.brid \
inner join his_bj_hc.OMR_BLZY w on w.jzxh=y.jzxh \
where M.ZXBZ<>1 \
and (w.BRTGJC like '%℃%' or w.BRTGJC like '%度%' or w.BRTGJC like '%T%' or w.BRTGJC like '%°%' or w.BRTGJC like '%mmHg%' \
or w.BRTGJC like '%分%' or w.BRTGJC like '%次%' or w.BRTGJC like '%P%' or w.BRTGJC like '%R%' or w.BRTGJC like '%p%' or w.BRTGJC like '%r%')
and y.KSSJ>=to_date('{0}','yyyy-MM-dd hh24:mi:ss') and y.KSSJ<to_date('{1}','yyyy-MM-dd hh24:mi:ss') \
order by y.KSSJ , w.JLXH ".format(str(d1), str(d2))
cursor = db.cursor()
#调用上述步骤3的db变量,连接Oracle数据库并创建游标
sj_bj = cursor.execute(sql_bj).fetchall()
# 连接oracle,主功能:查
注意:无论是Python连接Oracle创建数据表格还是连接Sql Serve数据库创建数据表格,方法是一模一样的。
import time
from sqlalchemy import create_engine, ForeignKey, UniqueConstraint, Index
from sqlalchemy import Column, Integer, String, Text
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, scoped_session
from sqlalchemy.orm import relationship
# sqlalchemy:将类和对象转换成SQL,然后使用数据API执行SQL并获取执行结果。与pymssql结合使用,功能可创建 表,删除表,不能修改表
import pymssql
from bs4 import BeautifulSoup
# BeautifulSoup最主要的功能是从网页抓取数据。提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。
# 它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
# 自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,
# 这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。
import re
import schedule, time
# 使用Schedule做Python任务调度
# 在工作中多少都会涉及到一些定时任务,比如定时邮件提醒等。
import datetime
import time
Base = declarative_base()
# declarative_base()是一个工厂函数,它为声明性类定义构造基类。init 在继承了Base。隶属sqlalchemy模块#之下功能可创建表,删除表,但不能修改表
# 查房记录
class Cfjl(Base):
'''
创建表格Cfjl,共22个表格,所有表格字段一模一样
'''
__tablename__ = 'T_Cfjl'
ID = Column(Integer, primary_key=True)
Zyh = Column(String(50))
Lsh = Column(String(50))
Title = Column(String(50))
NR = Column(Text)
YW = Column(Text)
BLBH = Column(String(50))
TJSJ = Column(String(50))
将上述步骤4利用sql查询所得的字段一个一个调出来,注意sql server查询返回的数据类型是一组对象,而oracle查询,返回的结果是一个个列表。
for res in sj:
#sql server查询返回的数据类型是一组对象,字段调用方式如下
zyh = res.BRBH
lsh = res.JZHM
blbh = res.BLBH
cysj = str(res.CYRQ)
lxnr = str(res.NR).encode('latin-1').decode('gbk', 'ignore')
jdxjsj = ''
r1 = Qrmyy_Config.Cfjl(Zyh=zyh, Lsh=lsh, Title='查房日期时间', NR=str(jdxjsj), YW=lxnr, BLBH=blbh, TJSJ=cysj)
#相当于sql server中的insert into数据插入sql语句,其中Qrmyy_Config.Cfjl点名指向步骤5的表格Cfjl
session.add(r1)
session.commit()
session1.close()
#sql server数据入库入表库功能:解析好的数据入库。
将上述步骤5利用sql查询所得的字段一个一个调出来,注意sql server查询返回的数据类型是一组对象,而此处为oracle查询,返回的结果是一个个列表。
for res_bj in sj_bj:
#sj_bj是sql查询返回的列表
zyh = res_bj[8]
lsh = res_bj[0]
blbh = res_bj[6]
cysj = res_bj[3]
lxnr = res_bj[4]
jdxjsj = res_bj[5]
r1_bj = "INSERT INTO Cfjl (ID,Brid,Mzh,jzxh,BLBH,Lsh,wd) \ VALUES({0},'{1}','{2}','{3}','{4}','{5}','{6}','{7}')".\
format('BJ_EY_MZBL_SEQ_ID.nextval', str(zyh), str(lsh), str(blbh), str(cysj),\ str(lxnr), str(jdxjsj))
#相当于Oracler中的insert into数据插入sql语句,其中Cfjl点名指向步骤5的表格Cfjl
cursor1.execute(r1_bj)
db.commit()
#Oracler数据入库入表库功能:解析好的数据入库。
cursor1.close()#关闭游标
conn.close()#关闭数据连接
1.定义
即文本的高级匹配模式,提供搜索,替换等功能。其本质是由一 系列字符和特殊符号构成的字串,这个字串即正则表达式。
2.原理
通过普通字符和有特定含义 的字符,来组成字符串,用以描述一 定的字符串规则,比如:重复,位置等,来表达某类特定的字符串,进而匹配。
匹配规则:每个普通字符匹配其对应的字符
In : re.findall('ab',"abcdefabcd")
Out: ['ab', 'ab'] 因为目标 字符串有两处 ab.
注意事项:正则表达式在 python 中也可以匹配中文
元字符: |
匹配规则: 匹配 | 两侧任意的正则表达式即可
In : re.findall('com|cn',"www.baidu.com/www.tmooc.cn")
Out: ['com', 'cn']
元字符: .
匹配规则:匹配除换行外的任意一 个字符,其中.可以代替任意字符.
In : re.findall('张.丰',"张三丰,张四丰,张五丰,张无忌")
Out: ['张三丰', '张四丰', '张五丰']
元字符: [字符集]
匹配规则: 匹配字符集 中的任意一个字符
表达形式:
[abc#!好] 表示 [] 中的任意一个字符
[0-9],[a-z],[A-Z] #表示区间内的任意一 个字符
[_#?0-9a-z] 混合书写,一般区间表达写在后面
In : re.findall('[aeiou]',"How are you!")
Out: ['o', 'a', 'e', 'o', 'u']
In [32]: re.findall('[A-Z]','Tom is not Jame')
Out[32]: ['T', 'J']
元字符:[^字符集]
匹配规则:匹配除了字符集以外的任意一 个字符
In : re.findall('[^0-9]',"Use 007 port")
Out: ['U', 's', 'e', ' ', ' ', 'p', 'o', 'r', 't'] #中间为空字符
元字符: ^
匹配规则:匹配目标 字符串的开头位置
In : re.findall('^Jame',"Jame,hello")
Out: ['Jame']
元字符: $
匹配规则: 匹配目标 字符串的结尾位置
In : re.findall('Jame$',"Hi,Jame")
Out: ['Jame']
规则技巧: ^ 和 $必然出现在正则表达式的开头和结尾处。如果两者同时出现,则中间的部分必须匹配整个目标 字符串的全部内容。
元字符: \A \Z
匹配规则: \A 表示开头位置 ,\Z 表示结尾位置
In [40]: re.findall('\A\w+\Z','Jame')
Out[40]: ['Jame']
#因为\w匹配普通字符,前后空字符被\A\Z匹配到了,加上连接+就是整个了.
元字符: *
匹配规则:匹配前面的字符出现 0次或多次
In : re.findall('wo*',"wooooo~~w!")
Out: ['wooooo', 'w']
In [33]: re.findall('[a-z]*','Tom is not Jam')
Out[33]: ['', 'om', '', 'is', '', 'not', '', '', 'am', '']
In [34]: re.findall('[A-Z][a-z]*','Tom is Jam')
Out[34]: ['Tom', 'Jam']
元字符:+
匹配规则: 匹配前面的字符出现 1次或多次
In : re.findall('[A-Z][a-z]+',"Hello World hello world Hello World")
Out: ['Hello', 'World', 'Hello', 'World']")
元字符:?
匹配规则: 匹配前面的字符出现 0次或 1 次
e.g. 匹配整数
In [28]: re.findall('-?[0-9]+',"Jame,age:18, -26")
Out[28]: ['18', '-26']
In [37]: re.findall('-?[0-9]',"Jame,age:18, -26")
Out[37]: ['1', '8', '-2', '6']
In [12]: re.findall('-?[0-9]+','2019?redown-15')
Out[12]: ['2019', '-15']
In [36]: re.findall('wo?','wooooo--w')
Out[36]: ['wo', 'w']
元字符:{ n}
匹配规则: 匹配前面的字符出现 n次
e.g. 匹配手机号码:因为手机号码都是 11位的,且第一 位为 1,后面 十个在 0-9中任意取.
In : re.findall('1[0-9]{n} 10}',"Jame:13886495728")
Out: ['13886495728']
元字符:{ m,n}
匹配规则: 匹配前面的字符出现 m-n次
e.g. 匹配 qq号,因为 qq都是 10位,前五个在 1-9中任意取一 个,后 5个在 0-9 中任意取一 个
In : re.findall('[1-9][0-9]{n} 5,10}',"Baron:1259296994")
Out: ['1259296994']
元字符: \d \D
匹配规则:\d 匹配任意数字字符,\D 匹配任意非数字字符
e.g. 匹配端口
In : re.findall('\d{1,5}',"Mysql: 3306, http:80")
Out: ['3306', '80']
In [38]: re.findall('\D{1,5}',"Mysql: 3306, http:80")
Out[38]: ['Mysql', ': ', ', htt', 'p:']
元字符: \w \W
匹配规则: \w 匹配普通字符,\W 匹配非普通字符
说明: 普通字符指数字,字母,下划线,汉字 。
e.g. 注意'+'连接作用.
In : re.findall('\w+',"server_port = 8888")
Out: ['server_port', '8888']
In [17]: re.findall('\W+','server_port=8888')
Out[17]: ['=']
元字符: \s \S
匹配规则: \s 匹配空字符,\S 匹配非空字符
说明: 空字符指 空格 \r \n \t \v \f 字符
In : re.findall('\w+\s+\w+',"hello world")
Out: ['hello world']
In [19]: re.findall('\S+','hello world')
Out[19]: ['hello', 'world']
In [39]: re.findall('\s+','hello world')
Out[39]: [' ']
元字符: \b \B
匹配规则: \b 表示单词边界,\B 表示非单词边界
说明:单词边界指数字字母(汉字)下划线与其他字符的交界位置 。
In : re.findall(r'bis\b',"This is a test.")
Out: ['is'] 因为 is去前后两端.
In [21]: re.findall('is','this is a test')
Out[21]: ['is', 'is'] 因为有两个 is.
1.如果使用正则表达式匹配特殊字符则需要加 \ 表示 转义 。
特殊字符: . * + ? ^ $ [] () {} | \
e.g. 匹配特殊字符 . 时使用 \d. 表示 本身含义
In [41]: re.findall('-?\d+\.?\d+','12 34 -1 1.56 -3.5')
Out[41]: ['12', '34', '1.56', '-3.5']
In [42]: re.findall('-?\d+\.?\d*','12 34 -1 1.56 -3.5')
Out[42]: ['12', '34', '-1', '1.56', '-3.5']
In [24]: re.findall('\$\d+','count:$100')
Out[24]: ['$100']
In [28]: re.findall('\\$\\d+','count:$100')
Out[28]: ['$100']
In [25]: re.findall('$\d+','count:$100')
Out[25]: []
2.在编程语言中,常使用原生字符串 书写正则表达式避免多重转义 的麻烦。
python 字符串 --> 正则 --> 目标 字符串
"\\$\\d+" 解析为 \$\d+ 匹配 "$100"
"\\$\\d+" 等同于 r"\$\d+"
1.定义
贪婪模式: 默认情况下,匹配重复的元字符总是尽可能多的向后匹配内容。比如: * + ? {n} m,n}
非贪婪模式(懒惰模式): 让匹配重复的元字符尽可能少的向后匹配内容。
2.贪婪模式转换为非贪婪模式
在匹配重复元字符后加 ‘?’ 号即可
* : *?
+ : +?
? : ??
{m,n} : {m,n}?
In : re.findall(r'\(.+?\)',"(abcd)efgh(higk)")
Out: ['(abcd)', '(higk)']
1.定义
在正则表达式中,以()建立正则表达式的内部分组,子组是正则表达式的一 部分,可以作为内部整体操作对象。
2.作用
可以被作为整体操作,改变元字符的操作对象
e.g. 改变 + 号 重复的对象
In : re.search(r'(ab)+',"ababababab").group()
Out: 'ababababab'
e.g. 改变 | 号 操作对象
In : re.search(r'(王|李)\d \D w{n} 1,3}',"王者荣耀").group()
Out: '王者荣耀'
可以通过编程语言某些接口 获取匹配内容中,子组对应的内容部分
e.g. 获取 url 协议类型
In : e.search(r'(https|http|ftp|file)://\d \D S+',"https://www.baidu.com").group(1)
Out: https
3.捕获组
可以给正则表达式的子组起一 个名字,表达该子组的意义 。这种有名称的子组即为捕获组。
格式:(?P
e.g. 给子组命名为 "pig"
In : re.search(r'(?Pab)+' ,"ababababab").group('pig')
Out: 'ab'
4.注意事项
一 个正则表达式中可以包含多个子组
子组可以嵌套,但是不要重叠或者嵌套结构复杂
子组序列号一 般从外到内,从左到右计数
regex = compile(pattern,flags = 0)
功能: 生产正则表达式对象
参数 : pattern 正则表达式
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 正则表达式对象
re.findall(pattern,string,flags = 0)
功能: 根据正则表达式匹配目标 字符串内容
参数 : pattern 正则表达式
string 目标 字符串
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 匹配到的内容列表, 如果正则表达式有子组则只能获取到子组对应的内容
regex.findall(string,pos,endpos)
功能: 根据正则表达式匹配目标 字符串内容
参数 : string 目标 字符串
pos 截取目标 字符串的开始匹配位置
endpos 截取目标 字符串的结束匹配位置
返回值: 匹配到的内容列表, 如果正则表达式有子组则只能获取到子组对应的内容
import re
s = '''Hello
北京'''
# regex = re.compile(r'\w',flags=re.A)#只能匹配ascii码['H', 'e', 'l', 'l', 'o']
# regex = re.compile(r'[a-z]+',flags=re.I)#匹配忽略字母大小写['Hello']
# regex = re.compile(r'.+')#['Hello', '北京']
# regex = re.compile(r'.+',flags= re.S)#使.可以匹配换行['Hello\n北京']
# regex = re.compile(r'^北京')#[]
# regex = re.compile(r'^北京',flags=re.M)#使^ $可以匹配每一行的开头结尾位置['北京']
# regex = re.compile(r'Hello$')#[]
regex = re.compile(r'Hello$',flags=re.M)#['Hello']
l = regex.findall(s)
print(l)
re.split(pattern,string,flags = 0)
功能: 使用正则表达式匹配内容, 切割目标 字符串
参数 : pattern 正则表达式
string 目标 字符串
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 切割后的内容列表
re.sub(pattern,replace,string,max,flags = 0)
功能: 使用一 个字符串替换正则表达式匹配到的内容
参数 : pattern 正则表达式
replace 替换的字符串
string 目标 字符串
max 最多替换几处, 默认替换全部
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 替换后的字符串
re.subn(pattern,replace,string,max,flags = 0)
功能: 使用一 个字符串替换正则表达式匹配到的内容
参数 : pattern 正则表达式
replace 替换的字符串
string 目标 字符串
max 最多替换几处, 默认替换全部
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 替换后的字符串和替换了几处
import re
s = 'alex:1995,sunny:1991'
# 使用正则表达式匹配内容 , 切割目标字符串
l = re.split(r'[,:]',s)
print(l) #['alex', '1995', 'sunny', '1991']
# 使用一个字符串替换正则表达式匹配到的内容
# s = re.sub(r':','-',s,1)
# print(s) #alex-1995,sunny:1991
# 使用一个字符串替换正则表达式匹配到的内容
s = re.subn(r':','-',s,1)
print(s) #('alex-1995,sunny:1991', 1)
re.finditer(pattern,string,flags = 0)
功能: 根据正则表达式匹配目标 字符串内容
参数 : pattern 正则表达式
string 目标 字符串
flags 功能标 志位, 扩展正则表达式的匹配
返回值: 匹配结果的迭代器
import re
s = ' 今年是 2019 年 , 建国 70 周年 '
pattern = r'\d+' 匹配所有数字
item = re.finditer(pattern,s)
for i in item:
print(i.group()) #2019 70
re.fullmatch(pattern,string,flags=0)
功能:完全匹配某个目标 字符串
参数 :pattern 正则
string 目标 字符串
返回值:匹配内容 match object
import re
s = " 今年是 2019 年 , 建国 70 周年 "
# 完全匹配
obj = re.fullmatch(r'.+',s)
print(obj.group())# 今年是 2019 年 , 建国 70 周年
re.match(pattern,string,flags=0)
功能:匹配某个目标 字符串开始位置
参数 :pattern 正则
string 目标 字符串
返回值:匹配内容 match object
import re
s = " 今年是 2019 年 , 建国 70 周年 "
# 匹配开始位置
obj = re.match(r'\w+',s)
print(obj.group()) # 今年是 2019 年
re.search(pattern,string,flags=0)
功能:匹配目标 字符串第一 个符合内容
参数 :pattern 正则
string 目标 字符串
返回值:匹配内容 match object
import re
s = " 今年是 2019 年 , 建国 70 周年 "
# 匹配第一处
obj = re.search(r'\d+',s)
print(obj.group()) #2019
compile 对象属性
【1 】 pattern : 正则表达式
【2 】 groups : 子组数 量
【3 】 groupindex : 捕获组名与组序号的字典
import re
#1.匹配一个.com邮箱格式的邮箱
print(re.findall(r'\w+@\w+\.com','[email protected]'))
#结果:['[email protected]']
#2.匹配一个密码8-12位,数字字母下划线构成
print(re.findall(r'\w{8,12}','zhiq14521'))
#结果:['zhiq14521']
#3.匹配一个数字,包含整数,小数,正数,负数,分数1/2及百分数4.6%
print(re.findall(r'-?\d+\.?/?\d*%?','1 -21 12.5 -12.8 0 1/3 4.6% '))
#结果:['1', '-21', '12.5', '-12.8', '0', '1/3', '4.6%']
#4.匹配一段文字中以大写字母开头的单词,注意文字中可能含有ipython这种,不算大写字母开头,H-base这种算大写字母开头,BSD也是.
print(re.findall(r'\b[A-Z][-_a-zA-Z]*','Hello iPython H-base BSD'))
#结果:['Hello', 'H-base', 'BSD']
#每个普通字符匹配其对应的字符,此处ab有两处,则结果也是两处
print(re.findall('ab','abcdefabcd'))
#结果:['ab', 'ab']
#匹配'|'或,两侧任意的正则表达式即可
print(re.findall('com|cn','www.baidu.com/www.twoo.cn'))
#结果:['com', 'cn']
#匹配除换行外的任意一个字符,其中.可以代替任意字符
print(re.findall('张.丰','张三丰,张无忌,张四丰'))
#结果:['张三丰', '张四丰']
#匹配字符集中的任意一个字符
print(re.findall('[aeiou]','how are you'))
#结果:['o', 'a', 'e', 'o', 'u']
print(re.findall('[A-Z]','Tom is Jam' ))
#结果:['T', 'J']
#匹配除了字符集以外的任意一个字符
print(re.findall('[^0-9]','use 007 port'))
#结果:['u', 's', 'e', ' ', ' ', 'p', 'o', 'r', 't']
#匹配目标字符串的开头位置
print(re.findall('^tom','tom is jame'))
#结果:['tom']
#匹配目标字符串的结尾位置
print(re.findall('tom$','jame is tom'))
#结果:['tom']
#匹配前面的字符出现0次或多次
print(re.findall('wo*','wooooooooooo--w!'))
#结果:['wooooooooooo', 'w']
print(re.findall('[a-z]*','Tom is not Jam'))
#结果:['', 'om', '', 'is', '', 'not', '', '', 'am', '']
print(re.findall('[A-Z][a-z]*','Tom is Jam'))
#结果:['Tom', 'Jam']
#匹配前面的字符出现1次或多次
print(re.findall('[A-Z][a-z]+',"Hello World hello world Hello World"))
#结果:['Hello', 'World', 'Hello', 'World']
#匹配前面的字符出现0次或1次
print(re.findall('-?[0-9]+',"Jame,age:18, -26"))
#结果:['18', '-26']
print(re.findall('[0-9]?',"Jame,age:18, -26"))
#结果:['', '', '', '', '', '', '', '', '', '1', '8', '', '', '', '2', '6', '']
print(re.findall('-?[0-9]',"Jame,age:18, -26"))
#结果:['1', '8', '-2', '6']
print(re.findall('-?[0-9]+','2019?redown-15'))
#结果:['2019', '-15']
print(re.findall('wo?','wooooo--w'))
#结果:['wo', 'w']
#匹配前面的字符出现n次,因为手机号码都是11位的,且第一位为1,后面十个在0-9中任意取.
print(re.findall('1[0-9]{10}',"Jame:13886495728"))
#结果:['13886495728']
#匹配前面的字符出现m-n次,因为qq都是10位,前五个在1-9中任意取一个,后5个在0-9中任意取一个
print(re.findall('[1-9][0-9]{5,10}',"Baron:1259296994"))
#结果:['1259296994']
# \d 匹配任意数字字符 \D 匹配任意非数字字符
print(re.findall('\d{1,5}',"Mysql: 3306, http:80"))
#结果:['3306', '80']
print(re.findall('\D{1,5}',"Mysql: 3306, http:80"))
#结果:['Mysql', ': ', ', htt', 'p:']
#\w 匹配普通字符,\W 匹配非普通字符
print(re.findall('\w+',"server_port = 8888"))
#结果:['server_port', '8888']
print(re.findall('\W+','server_port=8888'))
#结果:['=']
#\s 匹配空字符,\S 匹配非空字符
print(re.findall('\S+','hello world'))
#结果:['hello', 'world']
print(re.findall('\s+','hello world'))
#结果:[' ']
print(re.findall('\w+\s+\w+','hello world'))
#结果:['hello world']
#\A 表示开头位置,\Z 表示结尾位置,因为\w匹配普通字符,前后空字符被\A\Z匹配到了,加上连接+就是整个了.
print(re.findall('\A\w+\Z','Jame'))
#结果:['Jame']
print(re.findall('\A','Jame'))
#结果:['']
print(re.findall('\Z','Jame'))
#结果:['']
#\b 表示单词边界,\B 表示非单词边界
print(re.findall(r'\bis\b',"This is a test."))#is去除前后两端
#结果:['is']
print(re.findall('is','this is a test'))#两个is
#结果:['is', 'is']
print(re.findall(r'a*','abcdefg'))
#结果:['a', '', '', '', '', '', '', '']
print(re.findall('a*','abcdefg'))
#结果:['a', '', '', '', '', '', '', '']
print(re.findall(r'a+','abcdefg'))
#结果:['a']
print(re.findall('a+','abcdefg'))
#结果:['a']
print(re.findall('-?\d+\.?\d+','12 34 -1 1.56 -3.5'))
#结果:['12', '34', '1.56', '-3.5']
print(re.findall('-?\d+\.?\d*','12 34 -1 1.56 -3.5'))
#结果:['12', '34', '-1', '1.56', '-3.5']
print(re.findall('\$\d+','count:$100'))
#结果:['$100']
print(re.findall('$\d+','count:$100'))
#结果:[]
print(re.findall('\\$\\d+','count:$100'))
#结果:['$100']
print(re.findall(r'\(.+?\)',"(abcd)efgh(higk)"))
#结果:['(abcd)', '(higk)']
print(re.findall(r'\(.+\)',"(abcd)efgh(higk)"))
#结果:['(abcd)efgh(higk)']
print(re.findall(r'ab+','abababababab'))
#结果:['ab', 'ab', 'ab', 'ab', 'ab', 'ab']
print(re.search(r'(ab)+','abababab').group())
#结果:abababab
print(re.search(r'王|李\w{1,3}','王者荣耀').group())
#结果:王
print(re.search(r'王|李\w{1,3}','李世民').group())
#结果:李世民
print(re.search(r'(王|李)\w{1,3}','王者荣耀').group())
#结果:王者荣耀
print(re.search(r'(https|http|ftp|file)://\S+',"https://www.baidu.com").group(1))
#结果:https
print(re.search(r'(?Pab)+' ,'ababababab').group('name'))
#结果:ab
print(re.search(r'\d+','360733199102200512').group())
#结果:360733199102200512
print(re.search(r'\d{18}','360733199102200512').group())
#结果:360733199102200512
print(re.search(r'\d{17}(\d|x)','36073319910220051x').group())
#结果:36073319910220051x
print(re.findall(r'(\w+):(\d+)','alex:1995,sunny:1991'))
#结果:[('alex', '1995'), ('sunny', '1991')]
pos 匹配的目标 字符串开始位置
endpos 匹配的目标 字符串结束位置
re 正则表达式
string 目标 字符串
lastgroup 最后一 组的名称
lastindex 最后一 组的序号
span() 获取匹配内容的起止位置
start() 获取匹配内容的开始位置
end() 获取匹配内容的结束位置
groupdict() 获取捕获组字典 ,组名为键,对应内容为值
groups() 获取子组对应内容
group(n = 0)
功能:获取 match 对象匹配内容
参数 :默认为 0表示 获取整个 match 对象内容,如果是序列号或者组名则表示 获取对应子组内容
返回值:匹配字符串
import re
pattern = r'(ab)cd(?Pef)'
regex = re.compile(pattern)
info = regex.search('abcdefghi')#match 对象
# 属性变量
print(info.pos) #0
print(info.endpos) #9
print(info.re)#re.compile('(ab)cd(?Pef)')
print(info.string) #abcdefghi
print(info.lastgroup)#name
print(info.lastindex)#2
print('----------')
# 属性方法
print(info.span()) #(0, 6)
print(info.start()) #0
print(info.end()) #6
print(info.groups()) #('ab', 'ef')
print(info.groupdict()) #{'name': 'ef'}
print(info.group()) #abcdef
print(info.group('name')) #ef
1.使用函数 :re模块调用的匹配函数 。如:re.compile,re.findall,re.search…
2.作用:扩展丰富正则表达式的匹配功能
3.常用 flag
> A == ASCII 元字符只能匹配 ascii 码
> I == IGNORECASE 匹配忽略字母大小写
> S == DOTALL 使 . 可以匹配换行
> M == MULTILINE 使 ^ $可以匹配每一行的开头结尾位置
4.使用多个 flag
方法 :使用按位或连接
e.g. : flags = re.I | re.A
import re
s = '''Hello
北京 '''
regex = re.compile(r'\w',flags=re.A)
# 只能匹配 ascii 码 ['H', 'e', 'l', 'l', 'o']
regex = re.compile(r'[a-z]+',flags=re.I)
# 匹配忽略字母大小写 ['Hello']
regex = re.compile(r'.+') #['Hello', ' 北京 ']
regex = re.compile(r'.+',flags= re.S)
# 使 . 可以匹配换行 #['Hello\n 北京 ']
regex = re.compile(r'^ 北京 ') #[]
regex = re.compile(r'^ 北京 ',flags=re.M)
#[' 北京 ']
# 使 ^ $ 可以匹配每一行的开头结尾位置
regex = re.compile(r'Hello$') #[]
regex = re.compile(r'Hello$',flags=re.M)
#['Hello']
l = regex.findall(s)
print(l)
import re
def get_address(port):
f = open('exc.txt', 'r')
while True:#获取段落
data = ''
for line in f:
if line == '\n':
break
data += line
if not data:#文件已经结束
break
info = re.match(port,data)#判断是不是想要的段落
if info:#如果info不是None说明找到目标段落
print(data)
# pattern = r'[0-9a-f]{4}\.[0-9a-f]{4}\.[0-9a-f]{4}'
pattern = r'([0-9]{1,3}\.){3}[0-9]{1,3}/\d+|Unknow'
address = re.search(pattern,data).group()
return address
if __name__=='__main__':
port = input('端口:')
print(get_address(port))
#文献解析第一步#clear_unusual.py:清理掉没有内容或者乱码的txt文档的程序
import os
import codecs
import pickle
import re
import json
from time import *
path = '//10.132.20.100/nlpdata/all/100100'
def scan_txt():
'''
遍历指定文件夹,显示文件夹所有文件名
:return:
'''
file_list = []
for root, dirs, files in os.walk(path):
for file in files:
if os.path.splitext(file)[1] == '.txt':
file_list.append(os.path.join(root, file))
return file_list
def process_txt(lines_list):
'''
循环清理掉所有乱码及扫描档文献
:param lines_list:
:return:
'''
cleat_list = []
for line1 in lines_list:
# print(line1)
new_line = line1.strip()
print(len(new_line))
if re.search('^一、', new_line) or re.search('^二、', new_line) or re.search('\d%$', new_line) \
or re.search('[*?+#&^@$]', new_line) or re.search('^(\d)', new_line) or re.search('(\d)$', new_line) \
or re.search('.jpg', new_line) or re.search('\d$', new_line) or re.search('^\d', new_line) \
or re.search('http', new_line) or re.search('www', new_line) or re.search('---*', new_line):
continue
else:
cleat_list.append(new_line)
return cleat_list
def main():
'''
清除所有以.pdf和.pdfbox.txt结尾的重复txt文件及清除所有扫描档文件并将其文件名保存再yichang01.txt文档中
:return: 正常有数据的文件名保存在file01.txt文档中以便下次调用
'''
begin_time = time()
file_list = scan_txt()
print(file_list)
print(len(file_list))
for filename in file_list:
if filename.endswith('.pdf.pdfbox.txt'):
print(filename)
with open('D:/liu/yichang01.txt', 'a+', encoding='utf-8') as f1:
f1.write(filename + '\n')
else:
file1 = filename
title_dict = {}
lines_list = []
with open(file1, 'r', encoding='utf-8', errors='replace') as f:
for i in range(30):
lines = f.readline().strip()
lines_list.append(lines)
print(lines_list)
clear_list = process_txt(lines_list)
print(clear_list)
lines_str = ''.join(clear_list)
title_dict[filename] = lines_str
print(title_dict)
for key in title_dict:
if title_dict[key] == '':
with open('D:/liu/yichang01.txt', 'a+', encoding='utf-8') as f1:
f1.write(key + '\n')
else:
with open('D:/liu/file01.txt', 'a+', encoding='utf-8') as f2:
f2.write(key + '\n')
end_time = time()
run_time = end_time - begin_time
print('耗时:', run_time)
if __name__ == '__main__':
main()
#文献解析第二步:title_recognition.py:识别出标题的程序。
import os
import codecs
import pickle
import re
import json
import csv
from time import *
path = '//10.132.20.100/nlpdata/all/100100'
def scan_txt():
'''
遍历指定文件夹,显示文件夹所有文件名
:return:
'''
file_list = []
for root, dirs, files in os.walk(path):
for file in files:
if os.path.splitext(file)[1] == '.txt':
file_list.append(os.path.join(root, file))
return file_list
def get_info(lines_list):
'''
循环迭代处理所有文件,返回每个文件前三十行的内容
:param lines_list:
:return:
'''
info_list = []
for line in lines_list:
new_line = line.strip()
info_list.append(new_line)
print(info_list)
info_str = '***'.join(info_list)
return info_str
def recognize_eng(info_dict):
'''
将中英文文献区分开,中文文献路径存在一个列表中,英文文献路径存入另一个列表中
:param info_dict:
:return:
'''
eng_dict = {}
eng_list = []
for key, value in info_dict.items():
value2 = value.split('***')
for value3 in value2:
if re.search('[A-Za-z0-9]+', value3):
lines = value3
eng_list.append(lines)
eng_dict[key] = eng_list
return eng_dict
def process_txt(lines_list):
'''
循环清理掉所有文献的证券代码,公告编号
:param lines_list:
:return:
'''
clear_list = []
for line1 in lines_list:
new_line = line1
if re.search('证券代码', new_line) or re.search('股票代码', new_line) or re.search('Stock ID', new_line) \
or re.search('邮.*编', new_line) or re.search('Tel', new_line) or re.search('.*街.*号.*楼', new_line) \
or re.search('^一、', new_line) or re.search('^二、', new_line) or re.search('^\d.*\d$', new_line) \
or re.search('第.*页', new_line) or re.search('[*?+#&^@$]', new_line) or re.search('\dF', new_line):
continue
else:
clear_list.append(new_line)
if re.search('报.*告', new_line) or re.search('公.*告', new_line) or re.search('通.*知', new_line) \
or re.search('Notes', new_line) or re.search('Sheet', new_line) or re.search('Statement', new_line):
break
return clear_list
def process_txt2(lines_list2):
'''
循环清理掉所有文献的证券代码,公告编号
:param lines_list2:
:return:
'''
clear_list2 = []
for line1 in lines_list2:
new_line = line1
if re.search('证券代码', new_line) or re.search('股票代码', new_line) or re.search('Stock ID', new_line) \
or re.search('邮.*编', new_line) or re.search('Tel', new_line) or re.search('.*街.*号.*楼', new_line) \
or re.search('^一、', new_line) or re.search('^二、', new_line) or re.search('^\d.*\d$', new_line) \
or re.search('第.*页', new_line) or re.search('[*?+#&^@$]', new_line) or re.search('\dF', new_line):
continue
else:
clear_list2.append(new_line)
if re.search('报.*告', new_line) or re.search('公.*告', new_line) or re.search('通.*知', new_line) \
or re.search('Notes', new_line) or re.search('Sheet', new_line) or re.search('Statement', new_line):
break
return clear_list2
def recognize_title(clear_list):
'''
循环筛选出所有文献的标题
:param clear_list:
:return:
'''
title_list = []
for line1 in clear_list:
line2 = line1.strip()
if not re.search('[,:。、!√]', line2) and not re.search('序.*号', line2) and not re.search('页.*次', line2):
title_list.append(line2)
else:
break
print(title_list)
title_set = sorted(set(title_list), key=title_list.index)
title_str = ''.join(title_set)
print(title_str)
def recognize_title2(clear_list2):
'''
循环筛选出所有文献的标题
:param clear_list:
:return:
'''
title_list = []
for line1 in clear_list2:
line2 = line1.strip()
if not re.search('[,:.!√]', line2) and not re.search('序.*号', line2) and not re.search('页.*次', line2):
title_list.append(line2)
else:
break
print(title_list)
title_set = sorted(set(title_list), key=title_list.index)
title_str = ''.join(title_set)
print(title_str)
def remove_blank(title_dict):
'''
循环删除所有文献标题的空格
:param title_dict:
:return:
'''
clear_title_dict = {}
lines_list = []
for key, value in title_dict.items():
if re.search('[A-Za-z0-9]+', value):
lines = value
else:
lines = ''.join(value.split())
lines_list.append(lines)
title_set = sorted(set(lines_list), key=lines_list.index)
clear_title = ''.join(title_set)
clear_title_dict[key] = clear_title
return clear_title_dict
def make_tag(clear_title_dict):
'''
循环按规则给所有文件的标题打上标签
:param clear_title_dict:
:return:
'''
key_list = []
label_list = []
for key, value in clear_title_dict.items():
key_list.append(key)
if re.search('公告', value) or re.search('Announcement', value) or re.search('announcement', value):
label = '公告'
elif re.search('章程', value) or re.search('ARTICLES', value):
label = '章程'
elif re.search('报告', value) or re.search('快报', value) or re.search('Report', value):
label = '报告'
elif re.search('办法', value):
label = '办法'
else:
label = 'None'
label_list.append(label)
return label_list
def output_tag(clear_title_dict, label_list):
'''
输出文件路径,标签,以便后续查找出无标签的情况
:param clear_title_dict:
:param label_list:
:return:
'''
key_list = []
label_dict = {}
for key in clear_title_dict:
key_list.append(key)
for filename, label in zip(key_list, label_list):
label_dict[filename] = label
return label_dict
def output_json(clear_title_dict, label_list):
'''
输出最后结果,含文献路径,标题,标签
:param clear_title_dict:
:param label_list:
:return:
'''
key_list = []
value_list = []
result = {}
for key, value in clear_title_dict.items():
key_list.append(key)
value_list.append(value)
for filename, Title, label in zip(key_list, value_list, label_list):
result[filename] = {Title: label}
return result
def output_data(clear_title_dict, label_list):
'''
输出最后结果,含文献路径,标题,标签
:param clear_title_dict:
:param label_list:
:return:
'''
key_list = []
value_list = []
for key, value in clear_title_dict.items():
key_list.append(key)
value_list.append(value)
for filename, Title, label in zip(key_list, value_list, label_list):
consequence = {
'payload': {
'result': {
'data': [{
'fileID': filename,
'title': Title,
'label': label
}],
'totalCount': 1
},
'success': 'true'
},
}
return consequence
def output_info(clear_title_dict, label_list, info_dict):
'''
输出最后结果:含文献路径,文献内容,标题,标签
:param clear_title_dict:
:param label_list:
:param info_dict:
:return:
'''
key_list = []
value_list = []
content_list = []
show_dict = {}
for key, value in clear_title_dict.items():
key_list.append(key)
value_list.append(value)
for content in info_dict.values():
content_list.append(content)
for filename, info, Title, label in zip(key_list, content_list, value_list, label_list):
show_dict[filename] = {info: {Title: label}}
return show_dict
def main():
'''
清除所有以.pdf和.pdfbox.txt结尾的重复txt文件及清除所有扫描档文件并将其文件名保存再yichang01.txt文档中
:return: 正常有数据的文件名保存在file01.txt文档中以便下次调用
'''
begin_time = time()
file_list = scan_txt()
with open('test01.csv', 'a+', newline='', encoding='utf-8') as f7:
writer = csv.writer(f7, dialect='excel')
header = ['文件名', '标题候选文本', '文本标题', '文本类型']
writer.writerow(header)
with open('D:/liu/file01.txt', 'r', encoding='utf-8') as f1:
data_list = f1.readlines()
for data in data_list:
data1 = data.strip('\n')
title_dict = {}
info_dict = {}
lines_list = []
lines_list2 = []
with open(data1, 'r', encoding='utf-8', errors='replace') as f:
for i in range(30):
lines = f.readline()
lines_list.append(lines)
print(data1)
print(lines_list)
info_str = get_info(lines_list)
info_dict[data1] = info_str
print(info_dict)
eng_dict = recognize_eng(info_dict)
print(eng_dict)
clear_list = process_txt(lines_list)
print(clear_list)
title_str = recognize_title(clear_list)
title_dict[data1] = title_str
print(title_dict)
for key1 in title_dict:
if title_dict[key1] == '':
with open(key1, encoding='utf-8', errors='replace') as f1:
for i in range(30):
lines2 = f1.readline().strip()
lines_list2.append(lines2)
clear_list2 = process_txt2(lines_list2)
title_str02 = recognize_title2(clear_list2)
title_dict[key1] = title_str02
print(title_dict)
for key2 in title_dict:
if title_dict[key2] == '':
with open('D://liu/file60.txt', 'a+', encoding='utf-8') as f2:
f2.write(key2 + '\n')
for key in list(title_dict.keys()):
if not title_dict.get(key):
del title_dict[key]
clear_title_dict = remove_blank(title_dict)
label_list = make_tag(clear_title_dict)
label_dict = output_tag(clear_title_dict, label_list)
print(label_dict)
for key3 in label_dict:
if label_dict[key3] == 'None':
with open('D:/liu/file70.txt', 'a+', encoding='utf-8') as f8:
f8.write(key3 + '\n')
result = output_json(clear_title_dict, label_list)
consequence = output_data(clear_title_dict, label_list)
print(consequence)
print(type(consequence))
print(result)
result_json = json.dumps(result, ensure_ascii=False)
consequence_json = json.dumps(consequence, ensure_ascii=False, indent=4)
with open('D:/liu/test01.json', 'a+', encoding='utf-8') as f3:
f3.write(result_json + '\n')
with open('D:/liu/test01.txt', 'a+', encoding='utf-8') as f4:
f4.write(result_json + '\n')
with open('D:/liu/test10.json', 'a+', encoding='utf-8') as f5:
f5.write(consequence_json + '\n')
with open('D:/liu/test10.txt', 'a+', encoding='utf-8') as f6:
f6.write(consequence_json + '\n')
show_dict = output_info(clear_title_dict, label_list, info_dict)
print(show_dict)
with open('test01.csv', 'a+', newline='', encoding='utf-8') as f7:
writer = csv.writer(f7, dialect='excel')
for key10, value10 in show_dict.items():
for key20, value20 in value10.items():
for key30, value30 in value20.items():
writer.writerow([key10, key20, key30, value30])
end_time = time()
run_time = end_time - begin_time
print('耗时:', run_time)
if __name__ == '__main__':
main()
步骤一:借助sql语句查询出相应字段,提取信息,并得出其数据类型及整体数据结构;
步骤二:sql语句查询得数据类型为列表,一个个调出其中的字段,找到需要解析的字段(lxnr_bj);
步骤三:re正则结合体温关键字(T,体温,℃,度,°)解析的字段(lxnr_bj)得体温字段信息 ;
步骤四:re正则结合血压关键字(Bb,Pp,mmHg,血压)解析的字段(lxnr_bj)得收缩压,舒张压字段信息 ;
步骤五:re正则结合血压关键字(P,次/分,心率)解析的字段(lxnr_bj)得脉搏字段信息;
步骤六:re正则结合呼吸关键字(R,r,次/分,呼吸)解析的字段(lxnr_bj)得脉搏字段信息;
步骤七:连接Oracle数据库,将解析后得数据插入数据库,实现数据入库入表。
def aaa(self, a, b):
blType = 'mzbl'
sql_bj = "select y.KSSJ, m.BRID, m.MZHM, m.BRXM, m.jtdh lxdh, w.JLXH jlxh, w.BRTGJC DLNR, '' BLBH, w.JZXH jzxh from his_bj_hc.MS_BRDA m \
inner join his_bj_hc.YS_MZ_JZLS y on y.brbh=m.brid \
inner join his_bj_hc.OMR_BLZY w on w.jzxh=y.jzxh \
where M.ZXBZ<>1 \
and (w.BRTGJC like '%℃%' or w.BRTGJC like '%度%' or w.BRTGJC like '%T%' or w.BRTGJC like '%°%' or w.BRTGJC like '%mmHg%' \
or w.BRTGJC like '%分%' or w.BRTGJC like '%次%' or w.BRTGJC like '%P%' or w.BRTGJC like '%R%' or w.BRTGJC like '%p%' or w.BRTGJC like '%r%') \
and rownum<=10\
order by y.KSSJ , w.JLXH "
db_get = opdb_get()
cursor = db_get.cursor()
sj_bj = cursor.execute(sql_bj).fetchall()
# 连接oracle库并从原始readonly用户中查询到所需信息,主功能:查
print(type(sj_bj)) #
print(sj_bj)#[(datetime.datetime(2018, 1, 9, 0, 40, 44), 12109414, '91258149', '李建云', '13538286432', 387, '神志清,T{数字}℃,BP{收缩压}/{舒张压}mmHg,心率{心率数值}次/分。', None, 377), (datetime.datetime(2018, 1, 9, 0, 43, 37), 12109415, '91258150', '张万锦', '13682650486', 388, '神志清,T37℃,BP126/80mmHg,心率76次/分。神志清楚,查体合作,一般情况可,心肺听诊无异常,腹平软,无压痛,无反跳痛,墨菲氏征(—),右侧肾区叩击痛,肠鸣音3次/分钟。', None, 378), (datetime.datetime(2018, 12, 6, 20, 29, 8), 12389299, '91775912', '吴灏', '13510250655', 174, '神志清,T37℃,心率120次/分,R 32次/分。神志清楚,精神反应可,全身皮肤无黄染、皮疹,结膜无充血,眼球运动自如,鼻翼无扇动,唇红,无杨梅舌,咽部充血,未见疱疹,双侧扁桃体I°肿大,未见脓点,呼吸平顺,双肺呼吸音粗,未闻及干湿罗音,心音有力,律齐,各瓣膜听诊区未闻及杂音;腹平软,肝脾肋下未触及,肠鸣音正常,肌张力正常。生理反射存在,病理反射未引出。手足未见皮疹。躯干部散在红色皮疹', None, 629825), (datetime.datetime(2018, 12, 6, 20, 29, 19), 12259981, '91526408', '徐莉涵', '13691859246', 251, '神志清,T37℃,心率120次/分,R 32次/分。神志清楚,精神反应可,全身皮肤无黄染、皮疹,结膜无充血,眼球运动自如,鼻翼无扇动,唇红,无杨梅舌,咽部充血,未见疱疹,双侧扁桃体I°肿大,未见脓点,呼吸平顺,双肺呼吸音粗,未闻及干湿罗音,心音有力,律齐,各瓣膜听诊区未闻及杂音;腹平软,肝脾肋下未触及,肠鸣音正常,肌张力正常。生理反射存在,病理反射未引出。手足未见皮疹。', None, 629826), (datetime.datetime(2018, 12, 6, 20, 31, 16), 12126230, '91284569', '韦建璋', '18819009635', 192, '神志清,T36.5℃,BP120/80mmHg,心率80次/分。神志清楚,对答切题,伸舌不偏,瞳孔等大圆,光反射敏感,心肺无异常,腹平软,右上腹压痛(+)反跳痛(-),四肢无异常。', None, 629827), (datetime.datetime(2018, 12, 6, 20, 33, 27), 12295293, '91598597', '符帼英', '15767901698', 171, 'P72 次/分,神志清晰,颈软.甲状腺Ⅰ、II度肿大,无压痛,无血管杂音,双肺无异常,心率72次/分,律齐,未闻及杂音,腹平软.腹部无压痛、反跳痛,四肢无异常。', None, 629829), (datetime.datetime(2018, 12, 6, 20, 37, 32), 10688789, '902923800', '温召杰', '13510659001', 233, 'T:36 ℃.P:74次/分.R:19 次/分.BP:125 /75 mmHg.神志清楚,呼吸平稳,双肺呼吸音清晰,未闻及干湿罗音。心率74次/分,律齐,各瓣音区未闻及病理性杂音。腹平软,无压痛、反跳痛,双下肢不肿,四肢活动好。\r\n既往史及个人史同前。', None, 629831), (datetime.datetime(2018, 12, 6, 20, 40, 52), 12336048, '91676335', '马一菡', '13530615698', 224, '神志清,T37.3℃P 120次/分,R 30次/分。神志清楚,精神反应可,全身皮肤无黄染、皮疹,结膜无充血,眼球运动自如,鼻翼无扇动,唇红,无杨梅舌,咽部充血,未见疱疹,双侧扁桃体无肿大,未见脓点,,双肺呼吸音清晰,未闻及干湿罗音,心音有力,律齐,各瓣膜听诊区未闻及杂音;腹平软,全腹未扪及包块肝脾肋下未触及,肠鸣音活跃,肌张力正常。生理反射存在,病理反射未引出。手足未见皮疹。', None, 629833), (datetime.datetime(2018, 12, 6, 20, 40, 55), 12427232, '91849563', '张海荣', '13751080051', 170, 'T:37.9 ℃.P:78 次/分.R:19 次/分.BP:110 /70 mmHg.神志清楚,咽部充血.扁桃体无肿大.咽后壁滤泡增生.呼吸平稳,双肺呼吸音清晰,未闻及干湿罗音。心率78次/分,律齐,各瓣音区未闻及病理性杂音。腹平软,无压痛、反跳痛,双下肢不肿,四肢活动好。神志清,T{数字}℃,BP{收缩压}/{舒张压}mmHg,心率{心率数值}次/分。', None, 629834), (datetime.datetime(2018, 12, 6, 20, 43, 24), 12199534, '91408374', '汤诗琪', '13682569396', 169, '神志清,T38.3℃,心率120次/分,R 22次/分。神志清楚,精神反应可,全身皮肤无黄染、皮疹,结膜无充血,眼球运动自如,鼻翼无扇动,唇红,无杨梅舌,咽部充血,未见疱疹,双侧扁桃体I°肿大,未见脓点,呼吸平顺,双肺呼吸音粗,未闻及干湿罗音,心音有力,律齐,各瓣膜听诊区未闻及杂音;腹平软,肝脾肋下未触及,肠鸣音正常,肌张力正常。生理反射存在,病理反射未引出。手足未见皮。', None, 629835)]
#以上为步骤一:借助sql语句查询出相应字段,提取信息,并得出其数据类型及整体数据结构。
for res_bj in sj_bj:
jzxh_bj = res_bj[8]
dt_bj = res_bj[0]
rq_bj = dt_bj.strftime('%Y-%m-%d %H:%M:%S')
BRXM_bj = res_bj[3]
lxdh_bj = res_bj[4]
lsh_bj = res_bj[5]
mzh_bj = res_bj[2]
brid_bj = res_bj[1]
blbh_bj = res_bj[7]
lxnr_bj = res_bj[6]
print(lxnr_bj)
#神志清,T{数字}℃,BP{收缩压}/{舒张压}mmHg,心率{心率数值}次/分。
#神志清,T37℃,BP126/80mmHg,心率76次/分。神志清楚,查体合作,一般情况可,心肺听诊无异常,腹平软,无压痛,无反跳痛,墨菲氏征(—),右侧肾区叩击痛,肠鸣音3次/分钟。
#神志清,T37℃,心率120次/分,R 32次/分。神志清楚,精神反应可,全身皮肤无黄染、皮疹,结膜无充血,眼球运动自如,鼻翼无扇动,唇红,无杨梅舌,咽部充血,未见疱疹,双侧扁桃体I°肿大,未见脓点,呼吸平顺,双肺呼吸音粗,未闻及干湿罗音,心音有力,律齐,各瓣膜听诊区未闻及杂音;腹平软,肝脾肋下未触及,肠鸣音正常,肌张力正常。生理反射存在,病理反射未引出。手足未见皮疹。躯干部散在红色皮疹
#神志清,T37℃,心率120次/分,R 32次/分。神志清楚,精神反应可,全身皮肤无黄染、皮疹,结膜无充血,眼球运动自如,鼻翼无扇动,唇红,无杨梅舌,咽部充血,未见疱疹,双侧扁桃体I°肿大,未见脓点,呼吸平顺,双肺呼吸音粗,未闻及干湿罗音,心音有力,律齐,各瓣膜听诊区未闻及杂音;腹平软,肝脾肋下未触及,肠鸣音正常,肌张力正常。生理反射存在,病理反射未引出。手足未见皮疹。
#神志清,T36.5℃,BP120/80mmHg,心率80次/分。神志清楚,对答切题,伸舌不偏,瞳孔等大圆,光反射敏感,心肺无异常,腹平软,右上腹压痛(+)反跳痛(-),四肢无异常。
#P72 次/分,神志清晰,颈软.甲状腺Ⅰ、II度肿大,无压痛,无血管杂音,双肺无异常,心率72次/分,律齐,未闻及杂音,腹平软.腹部无压痛、反跳痛,四肢无异常。
#T:36 ℃.P:74次/分.R:19 次/分.BP:125 /75 mmHg.神志清楚,呼吸平稳,双肺呼吸音清晰,未闻及干湿罗音。心率74次/分,律齐,各瓣音区未闻及病理性杂音。腹平软,无压痛、反跳痛,双下肢不肿,四肢活动好。既往史及个人史同前。
#神志清,T37.3℃P 120次/分,R 30次/分。神志清楚,精神反应可,全身皮肤无黄染、皮疹,结膜无充血,眼球运动自如,鼻翼无扇动,唇红,无杨梅舌,咽部充血,未见疱疹,双侧扁桃体无肿大,未见脓点,,双肺呼吸音清晰,未闻及干湿罗音,心音有力,律齐,各瓣膜听诊区未闻及杂音;腹平软,全腹未扪及包块肝脾肋下未触及,肠鸣音活跃,肌张力正常。生理反射存在,病理反射未引出。手足未见皮疹。
#T:37.9 ℃.P:78 次/分.R:19 次/分.BP:110 /70 mmHg.神志清楚,咽部充血.扁桃体无肿大.咽后壁滤泡增生.呼吸平稳,双肺呼吸音清晰,未闻及干湿罗音。心率78次/分,律齐,各瓣音区未闻及病理性杂音。腹平软,无压痛、反跳痛,双下肢不肿,四肢活动好。神志清,T{数字}℃,BP{收缩压}/{舒张压}mmHg,心率{心率数值}次/分。
#神志清,T38.3℃,心率120次/分,R 22次/分。神志清楚,精神反应可,全身皮肤无黄染、皮疹,结膜无充血,眼球运动自如,鼻翼无扇动,唇红,无杨梅舌,咽部充血,未见疱疹,双侧扁桃体I°肿大,未见脓点,呼吸平顺,双肺呼吸音粗,未闻及干湿罗音,心音有力,律齐,各瓣膜听诊区未闻及杂音;腹平软,肝脾肋下未触及,肠鸣音正常,肌张力正常。生理反射存在,病理反射未引出。手足未见皮。
#以上为步骤二:sql语句查询得数据类型为列表,一个个调出其中的字段,找到需要解析的字段(lxnr_bj)
lxnr_bj = lxnr_bj.replace('\n', '')
lxnr_bj = lxnr_bj.replace('\r', '')
lxnr_bj = lxnr_bj.replace("'", '')
lxnr_bj = lxnr_bj.replace(" ", '')
#消除lxnr_bj字段字符串中间的的空格:如(BP:125 /75 mmHg)变成(BP:125/75mmHg)方便后续re正则匹配收缩压等.
#取出的单个lxnr_bj字段为字符串类型,采用上面三行代码替换消除掉字符串中的换行符,制表符,空格等
soup_bj = BeautifulSoup(lxnr_bj, "html.parser", from_encoding="utf-8")
# BeautifulSoup最主要的功能是从网页抓取数据。提供一些简单的、python式的函数用来处理导航、搜索、修改分析树等功能。
# 它是一个工具箱,通过解析文档为用户提供需要抓取的数据,因为简单,所以不需要多少代码就可以写出一个完整的应用程序。
# 自动将输入文档转换为Unicode编码,输出文档转换为utf-8编码。你不需要考虑编码方式,除非文档没有指定一个编码方式,
# 这时,Beautiful Soup就不能自动识别编码方式了。然后,你仅仅需要说明一下原始编码方式就可以了。
rewb_bj = re.compile('<[^>]+>')
soup_bj = rewb_bj.sub("", str(soup_bj))
#上述三行为多余重复代码
qjcs_bj = ''
bqbh_bj = ''
wd_bj = ''
ssy_bj = ''
szy_bj = ''
mb_bj = ''
hx_bj = ''
wd_resout_bj = re.findall(r'[T(体温)(温度)(T{)(T{数字})][::]? *[1-9]\d*[\.,,]?\d*|[1-9]\d*[\.,,]?\d*[℃度°]', str(lxnr_bj), re.S)
print(wd_resout_bj)
#正则匹配出(lxnr_bj字段)中的体温标志数据[] ['T37'] ['T37'] ['T37'] ['T36.5'] [] ['T:36'] ['T37.3'] ['T:37.9'] ['T38.3']
if wd_resout_bj:
#如果wd_resout_bj非空,则执行下行代码,清除文字,字母,保留数字
wd_resout_bj = re.findall(r'[1-9]\d*[\.,,]?\d*|0\.\d*[1-9]\d*', str(wd_resout_bj[0]), re.S)
print(wd_resout_bj)
#正则匹配出(lxnr_bj字段)中的体温数值数据 ['37'] ['37'] ['37'] ['36.5'] ['36'] ['37.3'] ['37.9'] ['38.3']
if wd_resout_bj:
wd_bj = wd_resout_bj[0].strip()
print(wd_bj)
#消除wd_resout_bj每个列表元素的前后空格,保留数字,即提取体温值(体温字段:wd_bj)
str1_bj = '体温-' + wd_bj
# print(str1_bj)
#以上为步骤三:re正则结合体温关键字(T,体温,℃,度,°)解析的字段(lxnr_bj)得体温字段信息
xy_resout_bj = re.findall(r'[Bb][Pp][::]?[^mmHg]*mmHg', str(lxnr_bj), re.S)
print(xy_resout_bj)
# 正则匹配出(lxnr_bj字段)中的血压标志数据['BP{收缩压}/{舒张压}mmHg'] ['BP126/80mmHg']
[] [] ['BP120/80mmHg'] [] ['BP:125 /75 mmHg']
[] ['BP:110 /70 mmHg', 'BP{收缩压}/{舒张压}mmHg'] []
if xy_resout_bj:
#如果xy_resout_bj非空,则执行下行代码,清除收缩压或BP等标志,保留数字到\或/结束
ssy_resout_bj = re.findall(r'[1-9]\d*\/', str(xy_resout_bj[0]), re.S)
print(ssy_resout_bj)#取出收缩压:[] ['126/'] ['120/'] ['125/'] ['110/']
if ssy_resout_bj:
ssy_resout_bj = re.findall(r'[1-9]\d*', str(ssy_resout_bj[0]), re.S)
print(ssy_resout_bj)#清除\或/取出收缩压数值['126'] ['120'] ['125'] ['110']
if ssy_resout_bj:
ssy_bj = ssy_resout_bj[0]
print(ssy_bj)#列表取出收缩压数值126 120 125 110即(收缩压字段:ssy_bj)
szy_resout_bj = re.findall(r'\/[1-9]\d*', str(xy_resout_bj[0]), re.S)
print(szy_resout_bj)#取出舒张压:[] ['/80'] ['/80'] ['/75'] ['/70']
if szy_resout_bj:
szy_resout_bj = re.findall(r'[1-9]\d*', str(szy_resout_bj[0]), re.S)
if szy_resout_bj:
szy_bj = szy_resout_bj[0]
print(szy_bj)#列表取出舒张压数值80 80 75 70即(收缩压字段:szy_bj)
str1_bj += ';血压-' + ssy_bj + '-' + szy_bj
#以上为步骤四:re正则结合血压关键字(Bb,Pp,mmHg,血压)解析的字段(lxnr_bj)得收缩压,舒张压字段信息
mb_resout_bj = re.findall(r'[Pp][::]?[^次\/分]*次\/分|[Pp][::]?[^bpm]*bpm|心率[::]?[^次\/分]*次\/分',str(lxnr_bj),re.S)
print(mb_resout_bj)
# 正则匹配出(lxnr_bj字段)中的心率标志数据['心率{心率数值}次/分'] ['心率76次/分']
['心率120次/分'] ['心率120次/分'] ['心率80次/分'] ['P72次/分', '心率72次/分']
['P:74次/分', '心率74次/分'] ['P120次/分'] ['P:78次/分', '心率78次/分', '心率{心率数值}次/分'] ['心率120次/分']
if mb_resout_bj:
mb_resout_bj = re.findall(r'[1-9]\d*', str(mb_resout_bj[0]), re.S)
print(mb_resout_bj)#清除汉字或字母取出心率数值[]['76']['120']['120']['80']['72'] ['74']['120']['78']['120']
if mb_resout_bj:
mb_bj = mb_resout_bj[0]
print(mb_bj)#列表取出心率数值76 120 120 80 72 74 120 78 120即脉搏字段:mb_bj
str1_bj += ';脉搏/心率-' + mb_bj
#以上为步骤五:re正则结合血压关键字(P,p,次\/分,心率)解析的字段(lxnr_bj)得脉搏字段信息
hx_resout_bj = re.findall(r'[Rr][::]?[^次\/分]*次\/分|呼吸[::]?[^次\/分]*次\/分', str(lxnr_bj), re.S)
print(hx_resout_bj)
# 正则匹配出(lxnr_bj字段)中的呼吸标志数据[] [] ['R32次/分'] ['R32次/分'] [] []
['R:19次/分', '呼吸平稳,双肺呼吸音清晰,未闻及干湿罗音。心率74次/分'] ['R30次/分']
['R:19次/分', '呼吸平稳,双肺呼吸音清晰,未闻及干湿罗音。心率78次/分'] ['R22次/分']
if hx_resout_bj:
hx_resout_bj = re.findall(r'[1-9]\d*', str(hx_resout_bj[0]), re.S)
print(hx_resout_bj)#清除汉字或字母取出呼吸数值['32']['32']['19']['30']['19']['22']
if hx_resout_bj:
hx_bj = hx_resout_bj[0]
print(hx_bj)#列表取出呼吸数值32 32 19 30 18 22即脉搏字段:hx_bj
str1_bj += ';呼吸-' + hx_bj
print(str1_bj)
#以上为步骤六:re正则结合呼吸关键字(R,r,次\/分,呼吸)解析的字段(lxnr_bj)得脉搏字段信息
db_save = opdb_save()
cursor1 = db_save.cursor()
# 连接oracle库的目标用户,用于存储上述查询到所需信息,主功能:连接
r1_bj = "INSERT INTO test_liu (ID,Brid, Mzh,jzxh,BLBH,Lsh,Title,wd,ssy,szy,mb,hx,lxdh,NR,Type,RECORD_TIME,BRXM,EXTRACT_TIME)VALUES({0},'{1}','{2}','{3}','{4}','{5}','{6}','{7}','{8}','{9}','{10}','{11}','{12}','{13}','{14}','{15}','{16}',{17})".format('BJ_EY_MZBL_SEQ_ID.nextval', str(brid_bj), str(mzh_bj), str(jzxh_bj), str(blbh_bj), str(lsh_bj), '体格检查',str(wd_bj), str(ssy_bj), str(szy_bj), str(mb_bj),str(hx_bj), str(lxdh_bj), str(lxnr_bj), str(blType), str(rq_bj), str(BRXM_bj), 'sysdate')
cursor1.execute(r1_bj)
db_save.commit()
cursor1.close()
db_save.close()
# 连接oracle的目标用户,主要功能:解析好的数据入库,即功能:oracle数据入库。
#以上为步骤七:连接Oracle数据库,将解析后得数据插入数据库,实现数据入库入表。
if __name__ == '__main__':
aaa("a", "b")#调用def aaa(self, a, b)函数
效果展示如图所示:
Re正则解析电子病例总结:主要是利用re正则匹配特征关键字,注意开头/末尾关键字就行。