Python:软件开发规范、正则表达式、爬虫

时间:2022-12-28 18:45:41

软件开发规范:

比如开发一个shop程序,下面得有一些目录,bin是可执行文件目录,conf(配置文件),core(主逻辑文件),data(数据文件),logs(写日志),README.txt(markdown语法,http://www.jianshu.com/p/1e402922ee32/入门指南)

 Python:软件开发规范、正则表达式、爬虫

PS 1:如果在这些目录下的文件里调用这些目录的其他文件,需要把shop这个目录加入到环境变量里,加入方法:

Import os,sys

path=os.path.dirname (os.path.dirname(__file__))   #把当前文件的父目录的父目录(在这里指shop)赋值给path

sys.path.append(path)   #把shop加入到环境变量里,就可以调用shop下的python模块

PS 2:

If __name==’__main__’:

   Print(‘XXXXXXXXX’)     #意思是只有当在自己文件里运行的时候,才走这个判断语句;如果是别的文件调用这个模块,则不走这个if判断语句;一般自测的时候用这个

正则表达式

re模块

在python中,如果使用正则表达式的话,需要导入re模块,re模块是一个内置模块,直接import就可以使用

import re

s='besttest is good'

1.print(re.match(r'best',s))  #字符串前面加r,代表原字符、不转义

#match方法接收3个参数,第一个是匹配的规则,也就是正则表达式,第二个是要查找的字符串,第三个参数不是必填的,用于控制正则表达式的匹配方式,看下面正则表达式的匹配模式。PS:是从字符串的第一个字符中匹配字符串(即从第一个字符开始匹配,比较麻烦),如果匹配到就返回一个对象,如果匹配不到,则返回None

#输出结果是:>>><_sre.SRE_Match object; span=(0, 4), match='best'>

print(re.match(r'best',s).group())   #加了group,输出结果是best

2.print(re.search('best',s))

#search方法的参数和match一样,和match方法不一样的是,match是从字符串里面的第一个字符开始找,而search方法则是从字符串的整个内容里面找,如果找到了就返回第一个(之后的不返回),找不到就返回None

#输出结果是:>>><_sre.SRE_Match object; span=(0, 4), match='best'>

3.print(re.findall(r'best',s))

#findall方法的参数上面的match、search一样,和他们不一样的是,findall会返回所有一个list,把所有匹配到的字符串,放到这个list里面,如果找不到的话,就返回一个空的list

#输出结果:>>> ['best']

4.print(re.sub(r'best','Best',s))

#sub方法和字符串的replace方法一样,是用来替换字符串的,把匹配到的值替换成一个新的字符串,接收3个参数,第一个是正则表达式,第二个是要替换成什么,第三个就是要查找的字符串,会返回一个新的字符串,如果匹配不到的话,返回原来的字符串

# 不会改变原来的字符串的值,只是返回一个新字符串

#输出结果:>>> Besttest is good

 5.print(re.split('best',s))

#split 方法和字符串的split方法一样,是用来分割字符的,按照匹配到的字符串进行分割,返回的是一个list,如果匹配不到的话,那返回的list中还是原来的字符串

#输出结果:>>> ['', 'test is good']

正则表达式常用符号:

1.数量词

'*'              匹配*前的这个字符0次或多次;*前的这个字符可有可无,无的话匹配空,有1个或多个的话就匹配1次或多次,其他字符必须有,没有的话返回为空。

例如:print(re.findall(r'be*s','beesttest very bestb bs besss'))

>>>['bees', 'bes', ‘bs’,'bes']

'+'              匹配+前的这个字符1次或多次,至少出现一次

print(re.findall(r'st+','besttest is best'))

>>> ['stt', 'st', 'st']

'?'                 匹配?前一个字符1次或0次,只是?前面的一个字符

print(re.findall(r'st?','besttest is best'))

>>> ['st', 'st', ‘s’, 'st']

'{m}'             匹配{}前的一个字符m次

print(re.findall(r't{2}','besttest is best'))

>>> ['tt']

'{n,m}'            匹配{}前一个字符n到m次

print(re.findall(r't{1,2}','besttest is best'))

>>> ['tt', 't', 't']

 

2.一般字符

'.'               默认匹配除\n之外的任意一个字符

print(re.findall(r'b.','besttest is good'))

>>> ['be']

print(re.findall(r's.','besttest is good'))

>>> ['st', 'st', 's']

'\'               转译符,前面的* + ?这样的字符都有特殊含义了,如果你想就想找它的话,那就得转译了,意思就是说如果你想让特殊字符失去以前的含义,那么就得给它前面加上\

print(re.findall(r'\?','besttest is best????'))

>>> ['?', '?', '?', '?']

'|'                匹配|左或|右的字符串,不是字符

print(re.findall(r'best|is','besttest is best'))

>>> ['best', 'is', 'best']

'[]'                  字符集合,某些字符的集合,匹配的时候是这个集合里面的任意一个字符就行

print(re.findall(r'be[stacj]','besttest is best bejson'))

>>>['bes', 'bes', 'bej']

在[]里面如果用‘^’                 在[]里面如果用^的话代表取反,也就是不包括的[]里这些字符串的字符

print(re.findall(r'be[^stac]','besttest is best bejson'))

>>>[ 'bej']

3.边界匹配(开头和结尾)

'^'                 匹配以什么字符开头,多行情况下匹配每一行的开头,比如判断一个网站是不是以https开头

print(re.findall(r'^b','besttest is good\nbest'))

>>> ['b']

print(re.findall(r'^b','besttest is good\nbest',re.M))    #多行模式要加第三个参数re.M

>>> ['b','b']

'$'                  匹配以什么字符结尾,多行情况下匹配每一行的结尾,比如判断图片是不是以jpg、gif等结尾

print(re.findall(r'd$','besttest is good'))

>>> ['d']

print(re.findall(r'd$','besttest is good\nbest is good',re.M))#多行模式

>>>['d','d']

'\A'                   仅以什么字符开头,和^不同的是它不能用多行模式

print(re.findall(r'\Ab','besttest is good'))

>>> ['b']

'\Z'                     仅以什么字符结尾,和$不同的是它不能用多行模式

print(re.findall(r'd\Z','besttest is good'))

>>> ['d']

4.预定义字符集合

'\d'                   匹配数字0-9

print(re.findall(r'\d','sdf2342312sdfs'))

>>>['2', '3', '4', '2', '3', '1', '2']

print(re.findall(r'\d+','sdf2342312sdfs'))

>>> ['2342312']

'\D'                    匹配非数字,包括字母、特殊字符等

print(re.findall(r'\D','sdf2342312sdfs'))

>>> ['s', 'd', 'f', 's', 'd', 'f', 's']

print(re.findall(r'\D+','sdf2342312sdfs'))

>>>['sdf', 'sdfs']

'\w'                       匹配所有的字母和数字、汉字

print(re.findall(r'\w+','sdf234%^2312sdfs&你好'))

>>> ['sdf234', '2312sdfs', '你好']

'\W'                       匹配不是字母和数字、汉字,指特殊符号和空格(匹配不了汉字)

print(re.findall(r'\W','sdf234%^2312sdfs&'))

>>>['%', '^', '&']

'\s'                           匹配空白字符、\t、\n、\r,空格#\t指一个tab键

print(re.findall('\s','axss\n\tsdf\t\r\t'))

>>> ['\n', '\t', '\t', '\r', '\t',’ ‘]

'\S'                           匹配非空白字符,不是\t、\n、\r,空格

print(re.findall('\S','axss\n\tsdf\t\r\t'))

>>> ['a', 'x', 's', 's', 's', 'd', 'f']

PS:[A-z]    所有的大小写字母

[a-z]     所有的小写字母

[A-Z]    所有的大写字母

[0-9]    所有的数字

5.分组匹配

分组匹配,就是把相同的规则写在一个组里,这样就可以直接对这个组进行一些匹配了。

例子:匹配ip地址(192.168.5.1,每一段都是1位或者3位的数字,后面有个点)

print(re.findall(r'\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}',"192.168.1.3"))         #\d{1,3}指匹配1-3次的数字

>>> ['192.168.1.3']            #不分组匹配的话得这么写,比较麻烦,但我们可以发现规律,除了第一个,后面的全都是'\.\d{1,3}',这样的话就可以用分组了,就把'\.\d{1,3}'当做一个整体,然后让他们出现3次就ok了,可以改成下面这样的:

print(re.search(r'\d{1,3}(\.\d{1,3}){3}',"192.168.1.3").group())

>>> 192.168.1.3            #这个是用search方法的,结果和上面的一样的,加group是让结果更直观,只有search和match有group方法

print(re.findall(r'\d{1,3}(\.\d{1,3}){3}',"192.168.1.3"))

>>> ['.3']                 #改成findall,发现结果错误。用match方法和search方法都是正常的,但findall方法这里有个坑。如果findall方法里面有分组的话,那结果就只是分组里面的内容(即小括号里的内容)。如果想让结果正确的话,就在分组最前面写上'?:',一个问号和一个冒号就好了,启用“不捕捉模式”:

print(re.findall(r'\d{1,3}(?:\.\d{1,3}){3}',"192.168.1.3"))

>>>['192.168.1.3']                  #findall方法加上?:结果就正确了

爬虫需要用的知识:

html是浏览器能解析的代码

requests模块

import requests

req=requests.get(‘http://baidu.com’)     #发get请求,打开一个url

print(req.text)          #获取网站返回的内容,即html

print(req.encoding)           #获取网站的编码,不同的网站编码不同,有UTF-8、ISO-8859-1等;在读写文件的时候需要用到编码