python字符串的使用详解
之前在网上看了关于python最基础的一些教程,看着都通俗易懂,但是在写的过程中却感觉还是很生涩。关于字符串的使用还是应该多写多练!
思路就是:以“#”为分割符,取左边的"teacher_id=123"([0]代表第一个索引位置),接着去除两边的空格(使用strip()),然后在以“=”为分割符,取“teacher_id"并去除两边的空格,打印出来的结果就是类似于”teacher_id:123"
去空格及特殊符号
s.strip().lstrip().rstrip('','')
复制字符串
#strcpy(sStr1,sStr2)
sStr1=''strcpy''
sStr2=sStr1
sStr1=''strcpy2''
printsStr2
连接字符串
#strcat(sStr1,sStr2)
sStr1=''strcat''
sStr2=''append''
sStr1+=sStr2
printsStr1
查找字符
#strchr(sStr1,sStr2)
#<0为未找到
sStr1=''strchr''
sStr2=''s''
nPos=sStr1.index(sStr2)
printnPos
比较字符串
#strcmp(sStr1,sStr2)
sStr1=''strchr''
sStr2=''strch''
printcmp(sStr1,sStr2)
扫描字符串是否包含指定的字符
#strspn(sStr1,sStr2)
sStr1=''12345678''
sStr2=''456''
#sStr1andcharsbothinsStr1andsStr2
printlen(sStr1andsStr2)
字符串长度
#strlen(sStr1)
sStr1=''strlen''
printlen(sStr1)
将字符串中的大小写转换
#strlwr(sStr1)
sStr1=''JCstrlwr''
sStr1=sStr1.upper()
#sStr1=sStr1.lower()
printsStr1
追加指定长度的字符串
#strncat(sStr1,sStr2,n)
sStr1=''12345''
sStr2=''abcdef''
n=3
sStr1+=sStr2[0:n]
printsStr1
字符串指定长度比较
#strncmp(sStr1,sStr2,n)
sStr1=''12345''
sStr2=''123bc''
n=3
printcmp(sStr1[0:n],sStr2[0:n])
复制指定长度的字符
#strncpy(sStr1,sStr2,n)
sStr1=''''
sStr2=''12345''
n=3
sStr1=sStr2[0:n]
printsStr1
将字符串前n个字符替换为指定的字符
#strnset(sStr1,ch,n)
sStr1=''12345''
ch=''r''
n=3
sStr1=nch+sStr1[3:]
printsStr1
扫描字符串
#strpbrk(sStr1,sStr2)
sStr1=''cekjgdklab''
sStr2=''gka''
nPos=-1
forcinsStr1:
ifcinsStr2:
nPos=sStr1.index(c)
break
printnPos
翻转字符串
#strrev(sStr1)
sStr1=''abcdefg''
sStr1=sStr1[::-1]
printsStr1
查找字符串
#strstr(sStr1,sStr2)
sStr1=''abcdefg''
sStr2=''cde''
printsStr1.find(sStr2)
分割字符串
#strtok(sStr1,sStr2)
sStr1=''ab,cde,fgh,ijk''
sStr2='',''
sStr1=sStr1[sStr1.find(sStr2)+1:]
printsStr1
#或者
s=''ab,cde,fgh,ijk''
print(s.split('',''))
连接字符串
delimiter='',''
mylist=[''Brazil'',''Russia'',''India'',''China'']
printdelimiter.join(mylist)
PHP中addslashes的实现
defaddslashes(s):
d={''"'':''\\"'',"''":"\\''","\0":"\\\0","\\":"\\\\"}
return''''.join(d.get(c,c)forcins)
s="John''Johny''Doe(a.k.a.\"SuperJoe\")\\\0"
prints
printaddslashes(s)
只显示字母与数字
defOnlyCharNum(s,oth=''''):
s2=s.lower();
fomart=''abcdefghijklmnopqrstuvwxyz0123456789''
forcins2:
ifnotcinfomart:
s=s.replace(c,'''');
returns;
print(OnlyStr("a000aa-b"))
截取字符串
str=’0123456789′
printstr[0:3]#截取第一位到第三位的字符
printstr[:]#截取字符串的全部字符
printstr[6:]#截取第七个字符到结尾
printstr[:-3]#截取从头开始到倒数第三个字符之前
printstr[2]#截取第三个字符
printstr[-1]#截取倒数第一个字符
printstr[::-1]#创造一个与原字符串顺序相反的字符串
printstr[-3:-1]#截取倒数第三位与倒数第一位之前的字符
printstr[-3:]#截取倒数第三位到结尾
printstr[:-5:-3]#逆序截取,具体啥意思没搞明白?
常用的字符串操作汇总如下:
①去除空格以及一些特殊符号(’#‘,’,‘,’|''等):
删除字符串两边的空格:str.strip()
删除字符串末尾的空格:str.lstrip()
删除字符串左边的空格:str.rstrip()
②字符串分割(默认为空白字符):
str.split()
③字符串查找:
str.find()#返回的是索引位置
④计算字符串长度:
len(str)
⑤字符串大小写:
str.upper()#字母大写
str.lower()#字母小写
str.capitalize()#首字母大写
str.istitle()#是否是首字母大写的
str.isupper()#字母是否便是大写
str.islower()#字母是否全是小写
用python也差不多一年多了,python应用最多的场景还是web快速开发、爬虫、自动化运维:写过简单网站、写过自动发帖脚本、写过收发邮件脚本、写过简单验证码识别脚本。
爬虫在开发过程中也有很多复用的过程,这里总结一下,以后也能省些事情。
1、基本抓取网页
get方法
importurllib2
url"http://www.baidu.com"
respons=urllib2.urlopen(url)
printresponse.read()
post方法
importurllib
importurllib2
url="http://abcde.com"
form={''name'':''abc'',''password'':''1234''}
form_data=urllib.urlencode(form)
request=urllib2.Request(url,form_data)
response=urllib2.urlopen(request)
printresponse.read()
2、使用代理IP
在开发爬虫过程中经常会遇到IP被封掉的情况,这时就需要用到代理IP;
在urllib2包中有ProxyHandler类,通过此类可以设置代理访问网页,如下代码片段:
importurllib2
proxy=urllib2.ProxyHandler({''http'':''127.0.0.1:8087''})
opener=urllib2.build_opener(proxy)
urllib2.install_opener(opener)
response=urllib2.urlopen(''http://www.baidu.com'')
printresponse.read()
3、Cookies处理
cookies是某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密),python提供了cookielib模块用于处理cookies,cookielib模块的主要作用是提供可存储cookie的对象,以便于与urllib2模块配合使用来访问Internet资源.
代码片段:
importurllib2,cookielib
cookie_support=urllib2.HTTPCookieProcessor(cookielib.CookieJar())
opener=urllib2.build_opener(cookie_support)
urllib2.install_opener(opener)content=urllib2.urlopen(''http://XXXX'').read(www.zycaihui.com)
关键在于CookieJar(),它用于管理HTTPcookie值、存储HTTP请求生成的cookie、向传出的HTTP请求添加cookie的对象。整个cookie都存储在内存中,对CookieJar实例进行垃圾回收后cookie也将丢失,所有过程都不需要单独去操作。
手动添加cookie
cookie="PHPSESSID=91rurfqm2329bopnosfu4fvmu7;kmsign=55d2c12c9b1e3;KMUID=b6Ejc1XSwPq9o756AxnBAg="
request.add_header("Cookie",cookie)
4、伪装成浏览器
某些网站反感爬虫的到访,于是对爬虫一律拒绝请求。所以用urllib2直接访问网站经常会出现HTTPError403:Forbidden的情况
对有些header要特别留意,Server端会针对这些header做检查
User-Agent有些Server或Proxy会检查该值,用来判断是否是浏览器发起的Request
Content-Type在使用REST接口时,Server会检查该值,用来确定HTTPBody中的内容该怎样解析。
这时可以通过修改http包中的header来实现,代码片段如下:
importurllib2
headers={
''User-Agent'':''Mozilla/5.0(Windows;U;WindowsNT6.1;en-US;rv:1.9.1.6)Gecko/20091201Firefox/3.5.6''
}
request=urllib2.Request(
url=''http://my.oschina.net/jhao104/blog?catalog=3463517'',
headers=headers
)
printurllib2.urlopen(request).read()
5、页面解析
对于页面解析最强大的当然是正则表达式,这个对于不同网站不同的使用者都不一样,就不用过多的说明,附两个比较好的网址:
正则表达式入门
正则表达式在线测试
其次就是解析库了,常用的有两个lxml和BeautifulSoup,对于这两个的使用介绍两个比较好的网站:
lxml
BeautifulSoup
对于这两个库,我的评价是,都是HTML/XML的处理库,Beautifulsoup纯python实现,效率低,但是功能实用,比如能用通过结果搜索获得某个HTML节点的源码;lxmlC语言编码,高效,支持Xpath
6、验证码的处理
对于一些简单的验证码,可以进行简单的识别。本人也只进行过一些简单的验证码识别。但是有些反人类的验证码,比如12306,可以通过打码平台进行人工打码,当然这是要付费的。
7、gzip压缩
有没有遇到过某些网页,不论怎么转码都是一团乱码。哈哈,那说明你还不知道许多web服务具有发送压缩数据的能力,这可以将网络线路上传输的大量数据消减60%以上。这尤其适用于XMLweb服务,因为XML数据的压缩率可以很高。
但是一般服务器不会为你发送压缩数据,除非你告诉服务器你可以处理压缩数据。
于是需要这样修改代码:
importurllib2,httplibrequest=urllib2.Request(''http://xxxx.www.edu800.cncom'')
request.add_header(''Accept-encoding'',''gzip'')1
opener=urllib2.build_opener()
f=opener.open(request)
这是关键:创建Request对象,添加一个Accept-encoding头信息告诉服务器你能接受gzip压缩数据
然后就是解压缩数据:
importStringIO
importgzip
compresseddata=f.read()
compressedstream=StringIO.StringIO(compresseddata)
gzipper=gzip.GzipFile(fileobj=compressedstream)
printgzipper.read()
8、多线程并发抓取
单线程太慢的话,就需要多线程了,这里给个简单的线程池模板这个程序只是简单地打印了1-10,但是可以看出是并发的。
虽然说python的多线程很鸡肋,但是对于爬虫这种网络频繁型,还是能一定程度提高效率的。
fromthreadingimportThread
fromQueueimportQueue
fromtimeimportsleep
#q是任务队列
#NUM是并发线程总数
#JOBS是有多少任务
q=Queue()
NUM=2
JOBS=10
#具体的处理函数,负责处理单个任务
defdo_somthing_using(arguments):
printarguments
#这个是工作进程,负责不断从队列取数据并处理
defworking():
whileTrue:
arguments=q.get()
do_somthing_using(arguments)
sleep(1)
q.task_done()
#forkNUM个线程等待队列
foriinrange(NUM):
t=Thread(target=working)
t.setDaemon(True)
t.start()
#把JOBS排入队列
foriinrange(JOBS):
q.put(i)
#等待所有JOBS完成
q.join()
第一形式
#!/usr/bin/envpython
#coding=utf-8
classPerson(object):#object表示继承自object类,Python3中可省略次内容
"""
ThisisasampleofClass
"""
breast=90#类的属性是静态变量
def__init__(self,name):#初始化方法self为对象实例本身
self.name=name
defget_name(self):#类的方法
returnself.name
defcolor(self,color):
d={}
d[self.name]=color;
returnd
if__name__=="__main__":
girl=Person("songjia")
printgirl.name
girl.name="liu"
printgirl.get_name()
printgirl.color("white")
girl.breast=80#修改实例的属性
printgirl.breast
printPerson.breast#类属性不会随实例属性的改变而改变
Person.breast=100
printPerson.breast
printgirl.breast
第二种形式
>>>__metaclass__=type
>>>classCC:
...pass
...
>>>cc=CC()
>>>cc.__class__
>>>type(cc)
实例
girl=Person("songjia")
类属性
>>>classA(object):#Python3:classA:
...x=7#类的属性
...
下面列出类的几种特殊属性的含义:
C.__name__:以字符串的形式,返回类的名字,注意这时候得到的仅仅是一个字符串,它不是一个类对象
C.__doc__:显示类的文档
C.__base__:类C的所有父类。如果是按照上面方式定义的类,应该显示object,因为以上所有类都继承了它。等到学习了“继承”,再来看这个属性,内容就丰富了
C.__dict__:以字典形式显示类的所有属性
C.__module__:类所在的模块
实例属性
>>>classA(object):#Python3:classA:
...x=7#类的属性
...
>>>foo=A()
>>>foo.x#实例属性
类中变量引用可变数据
>>>classB(object):
...y=[1,2,3]
>>>B.y#类属性
[1,2,3]
>>>bar=B()
>>>bar.y#实例属性
[1,2,3]
>>>bar.y.append(4)
>>>bar.y
[1,2,3,4]
>>>B.y
[1,2,3,4]
>>>B.y.append("aa")
>>>B.y
[1,2,3,4,''aa'']
>>>bar.y
[1,2,3,4,''aa'']
当类中变量引用的是可变对象是,类属性和实例属性都能直接修改这个对象,从而影响另一方的值。
访问限制
#!/usr/bin/envpython
#coding=utf-8
classPerson(object):
"""
ThisisasampleofClass
"""
def__init__(self,name):#初始化方法self为对象实例本身
self.__name=name#__xx双下划线表示类的私有变量
defget_name(self):#类的方法
returnself.__name#类的内部可以访问
if__name__=="__main__":
girl=Person("songjia")
printgirl.get_name()
printgirl._name#无法访问类的私有变量
文档字符串
在函数、类或者文件开头的部分写文档字符串说明,一般采用三重引号。这样写的最大好处是能够用help()函数看。
"""Thisispythonlesson"""
defstart_func(arg):
"""Thisisafunction."""
pass
classMyClass:
"""Thisismyclass."""
defmy_method(self,arg):
"""Thisismymethod."""
pass
继承
单继承
#!/usr/bin/envpython
#coding=utf-8
classPerson(object):#Python3:classPerson:
def__init__(self,name):
self.name=name
defheight(self,m):
h=dict((["height",m],))
returnh
defbreast(self,n):
b=dict((["breast",n],))
returnb
classGirl(Person):#继承
defget_name(self):
returnself.name
if__name__=="__main__":
cang=Girl("liuguoquan")
printcang.get_name()#Python3:print(cang.get_name()),下同,从略
printcang.height(160)
printcang.breast(90)
调用覆盖的方法
classGirl(Person):
def__init__(self,name):
#Person.__init__(self,name)#调用父类的方法
super(Girl,self).__init__(name)#调用父类的方法常用写法
self.real_name="Aoisola"
defget_name(self):
returnself.name
if__name__=="__main__":
cang=Girl("canglaoshi")
printcang.real_name
printcang.get_name()
printcang.height(160)
printcang.breast(90)
执行结果为:
Aoisola
canglaoshi
{''height'':160}
{''breast'':90}
多继承
#!/usr/bin/envpython
#coding=utf-8
classPerson(object):#Python3:classPerson:
defeye(self):
print"twoeyes"
defbreast(self,n):
print"Thebreastis:",n
classGirl(object):#Python3:classGril:
age=28
defcolor(self):
print"Thegirliswhite"
classHotGirl(Person,Girl):#多重继承
pass
if__name__=="__main__":
kong=HotGirl()
kong.eye()
kong.breast(90)
kong.color()
printkong.age
twoeyes
Thebreastis:90
Thegirliswhite
28
多重继承的顺序-广度优先
classK1(object):#Python3:classK1:
deffoo(self):
print"K1-foo"#Python3:print("K1-foo"),下同,从略
classK2(object):#Python3:classK2:
deffoo(self):
print"K2-foo"
defbar(self):
print"K2-bar"
classJ1(K1,K2):
pass
classJ2(K1,K2):
defbar(self):
print"J2-bar"
classC(J1,J2):
pass
if__name__=="__main__":
printC.__mro__
m=C()
m.foo()
m.bar()
K1-foo
J2-bar
代码中的printC.__mro__是要打印出类的继承顺序。从上面清晰看出来了。如果要执行foo()方法,首先看J1,没有,看J2,还没有,看J1里面的K1,有了,即C==>J1==>J2==>K1;bar()也是按照这个顺序,在J2中就找到了一个。
这种对继承属性和方法搜索的顺序称之为“广度优先”。
Python2的新式类,以及Python3中都是按照此顺序原则搜寻属性和方法的。
方法
绑定方法
#!/usr/bin/envpython
#coding=utf-8
classPerson(object):#Python3:classPerson:
defeye(self):
print"twoeyes"
defbreast(self,n):
print"Thebreastis:",n
classGirl(object):#Python3:classGril:
age=28
defcolor(self):
print"Thegirliswhite"
classHotGirl(Person,Girl):#多重继承
pass
if__name__=="__main__":
kong=HotGirl()#实例化实现了方法和实例的绑
kong.eye()#调用绑定方法
非绑定方法
在子类中,父类的方法就是非绑定方法,因为在子类中,没有建立父类的实例,却要是用父类的方法。
静态方法和类方法
#!/usr/bin/envpython
#coding=utf-8
__metaclass__=type
classStaticMethod:#静态方法
@staticmethod
deffoo():
print"Thisisstaticmethodfoo()."
classClassMethod:#类方法
@classmethod
defbar(cls):#类方法必须有cls参数
print"Thisisclassmethodbar()."
print"bar()ispartofclass:",cls.__name__
if__name__=="__main__":
static_foo=StaticMethod()#实例化
static_foo.foo()#实例调用静态方法
StaticMethod.foo()#通过类来调用静态方法
print""
class_bar=ClassMethod()
class_bar.bar()
ClassMethod.bar()
Thisisstaticmethodfoo().
Thisisstaticmethodfoo().
Thisisclassmethodbar().
bar()ispartofclass:ClassMethod
Thisisclassmethodbar().
bar()ispartofclass:ClassMethod
在python中:
@staticmethod表示下面的方法是静态方法
@classmethod表示下面的方法是类方法
多态和封装
多态
classCat:
defspeak(self):
print"meow!"
classDog:
defspeak(self):
print"woof!"
classBob:
defbow(self):
print"thankyou,thankyou!"
defspeak(self):
print"hello,welcometotheneighborhood!"
defdrive(self):
print"beep,beep!"
defcommand(pet):
pet.speak()
pets=[Cat(),Dog(),Bob()]
forpetinpets:
command(pet)
Python中的多态特点,Python不检查传入对象的类型,这种方式被称之为“隐式类型”(latentyping)或者“结构式类型”(structuraltyping),也被通俗的称为“鸭子类型”(ducktypeing),Python是弱类型语言。
Java会检查传入对象的类型,所以是强类型语言。
封装和私有化
要了解封装,离不开“私有化”,就是将类或者函数中的某些属性限制在某个区域之内,外部无法调用。
Python中私有化的方法也比较简单,就是在准备私有化的属性(包括方法、数据)名字前面加双下划线。例如:
#!/usr/bin/envpython
#coding=utf-8
classProtectMe(object):#Python3:classProtectMe:
def__init__(self):
self.me="qiwsir"
self.__name="kivi"#私有变量
def__python(self):#私有方法
print"IlovePython."
defcode(self):
print"Whichlanguagedoyoulike?"
self.__python()
if__name__=="__main__":
p=ProtectMe()
printp.me
printp.code()
如何将一个方法变成属性调用?
可以使用property函数。
#!/usr/bin/envpython
#coding=utf-8
classProtectMe(object):#Python3:classProtectMe:
def__init__(self):
self.me="qiwsir"
self.__name="kivi"#私有变量
def__python(self):#私有方法
print"IlovePython."
@property
defcode(self):
print"Whichlanguagedoyoulike?"
self.__python
if__name__=="__main__":
p=ProtectMe()
printp.me
printp.code#调用方法名即可
|
|