2023年6月29日发(作者:)
【python爬⾍系列】解析库第五节:python解析库5.1⽂本清洗1)编码解码:编码是信息从⼀种形式或格式转换为另⼀种形式的过程,解码则是编码的逆过程乱码的诞⽣就是编解码不⼀样造成的,只有编码和解码的⽅式⼀样才会正常显⽰编码:Encode解码:Decode⽐如你新建⼀个⽂本⽂档,就可以在下⽅看到编码,如图2)常见格式:ASCII(补码形式)计算机内部,所有信息最后都是⼀个⼆.进制⼀个字节byte是8位⼆进制,⼆进制有0和1两种状态,所以⼀个字节有256种状态,每个状态对应⼀个符号。 asci-共256个符号。上个世纪,美国制定了这套编码,英语字符和⼆进制⼀⼀对应,沿⽤到现在。⽐如空格是32,⼤写字母A是65。 字符⼀共128个, 这些字符只占⽤⼀个字节的后边7位,最前边统⼀为0Unicode(python2)(被称为上帝的馈赠):100多万个符号,把世界上所有的符号融⼊其中,每个符号都有独⼀⽆⼆ 的编码。⽐如U+0639代表阿拉伯字母Ain,U+4E25代表汉字严。不过存在的问题是,unicode转化为⼆进制需要很多空间,⽐如严的16进制4E25转化为⼆进制有15位(101) ,⾄少两个字节。其他更⼤的符号可能有5⼀-6个字节。英⽂字母只需要⼆进制的七位,所以在unicode中,⼀-般字符三到四个字节,会有空间浪费,⽂本⽂件因此⼤出好⼏倍,是⽆法接受的。UTF-8(Unicod中的,轻量级Unicod)⽬前最常见的unicode实现⽅式,还有uf- 16,utf-32等等。对于单字节的符号,字节第⼀位为0,后边7位是unicode码。对于英⽂字母,utf8和unicode是 ⼀样的。对于n字节的符号,第⼀个字节前边的n位都设为1,n+1为设 为0,后边字节的前两位⼀律为10。剩下的没有提及的为unicode。如果字节第⼀位为0,就是单独⼀个字符;如果第⼀位为1,则有多少个连续的1,就是⼏个字节严的unicode是4E25 (101)处于0000800 000FFFF范围内, 所以转化为utf8是111xxx1x0xxxxxxxxx,然后,从最后⼀个开始,依次填充unicode,得到⼗六进制E4B8A5。3)python编码解码编码解码⼀般是⼀⼀对应的,编解码格式应该⼀致,不⼀致可能导致编码问题乱码,或者⼲脆解析不了:例如:text = 'hello python 汉字'ens = ("utf-8") #编码⼀般是先转化,类似于加密print(ens)des = ("utf-8") #解码就是解密
print(des)输出:b'hello python xe6xb1x89xe5xadx97' #16进制hello python 汉字然⽽我们加上:ddns = ("ascii")print(ddns)就会报错:UnicodeDecodeError:
'ascii' codec can't decode byte 0xe6 in position 13这就是因为我们使⽤了错误的解码格式常⽤的编码⽅式应⽤:在Python中,编码解码常见于1.写⼊⽂本⽂件2.获取⽹页页⾯#编码⽅式应⽤1
获取⽹页页⾯时import requestshtml = ("")ng="utf-8"#ng="gbk" #中⽂print()#编码⽅式应⽤2
写⼊⽂本⽂件时text = "text"
with open ("",encoding="utf-8") as f:
(text)你可以在⽹页的源代码处查看⽹页相应的编码格式以达到确定采⽤哪种编码⽅式的⽬的:5.2 Python操作字符串1).根据任意多的分隔符操作字符串()可以设定分隔符,或者采⽤ ()右分割(针对于长⽂本处理,取出后边的⼏个),当然也可设定分割⼏个扩展知识: ⾃然语⾔处理: 正向分割,反向分割,双向分割如:text = "python"res1 = ("/")res2 = ("/",maxsplit=2) #从右边分割,分割成⼏个print(res1)print(res2)输出:['https:', '', 'python']['https:', '', 'python']2).在字符串开头结尾做⽂本匹配本⽅法适⽤于存储或者清洗数据的时候找到我们所需要的数据,注意⼤⼩写也是区分的。with() 匹配开头th() 匹配结尾如:text1 = "python⼊门"text2 = "go ⼊门"if with("python"): print(text1)else: print("no python book")if with("python"): print(text1)else: print("no python book")输出:python⼊门no python book3).字符串连接合并问题() 把容器⾥的东西按你⾃定义⽅式拼接值得注意的是它的写法要s = (",".join(res)),res是列表等如:(我们利⽤如下两种⽅式作为对⽐)res=["python","go","java","c"]#⽅法1tmp = ""for i in res: tmp+=iprint(tmp)
#⽅法⼆print(",".join(res))输出:pythongojavacpython,go,java,c
我们可以看到,两种都可以实现拼接,但显然第⼆种更加好,还可以⾃定义你的拼接设定4).字符串替换e() 字符串替换ate() ord映射替换我们⽇常写的爬⾍基本都是⼩的爬⾍⽽不是特别⼤的⼯程,所以我们往往习惯使⽤replace⽅法,⽽在⼤⼯程⾥,往往代码⾏要成千上万,那么利⽤replace⽅法是极其复杂的,我们需要⼀个⼀个的更改才⾏,⽽translate⽅法就不需要,这也是这两种⽅法的区别,使⽤⽅法如下:#替换⽅法translateins = "abcd" #替换前outs = "degf" #替换后str_trantab = ans(ins,outs) #前⾯写替换前,后⾯写替换后test_str = "abcd hijk lmn"print(test_ate(str_trantab))结果:degf hijk lmn5).去除不需要的字符()()(str)([chars])⽅法删除字符串开头和结尾指定的字符或字符序列(即不能删中间字符)。([chars])⽅法删除字符串开头指定的字符或字符序列(即不能删中间字符)。(l - left - strip 左侧,即开头)([chars])⽅法删除字符串结尾指定的字符或字符序列(即不能删中间字符)。(r - right - strip 右侧,即结尾)上⾯三个函数返回移除字符串string头尾指定的字符⽣成的新字符串,string本⾝不会发⽣改变。chars 指的是移除字符串头尾指定的字符序列,若其为空,则默认删除空⽩符:n、r、t、’ ',即:换⾏、回车、制表符、空格若其不为空时,找出字符串string中头尾部分含有的与chars中所包含的字符相同的字符,然后将这些字符去掉6).格式化替换%d %s传统替换格式Format()替换f“”替换res = "/f"#1.c语⾔传承传统替换⽅法print("/f=%s--%d"%('python',1))#2 format python2-3print("/f={}".format("python"))#3. f 3.6python新加p = 'python'print(f'/f={p}')输出:/f=/f=/f=python三种⽅法你都可以使⽤,但最好在⼀个项⽬⾥选择⼀个5.3正则表达式什么是正则表达式?正则表达式是对字符串操作的⼀种逻辑公式,就是⽤事先定义好的⼀些特定字符、及这些特定字符的组合,组成⼀个"规则字符串", 这个规则字符串"⽤来表达对字符串的⼀种过滤逻辑。on⾃带库,使⽤⽅法 import re即可导⼊修饰符:re.I* 使匹配对⼤⼩写不敏感re.L 做本地化识别( locale-aware )匹配re.M* 多⾏匹配,影响^和$re.S* 使匹配包括换⾏在内的所有字符(html匹配常⽤)re.U 根据Unicode字符集解析字符。这个标志影响lw, W, lb, .X 该标志通过给予你更灵活的格式以便你将正则表达式写得更易于理解。同时使⽤多个修饰符⽅法,利⽤ | 如:re.I|rn ,我们编写的正则表达式,String ,我们要匹配的字符串Flag,我们的修饰符1)(pattern,string,flag) 从⽂本开头开始匹配匹配string 开头,成功返回Match object, 失败返回None,只匹配⼀个。⽤group()提取结果2).search在string中进⾏搜索,成功返回Match object, 失败返回None, 只匹配⼀个。⽤group()提取结果例:**import retext = '百度⼀下' '跳转'print(text)res = ('href=".*?"',text,re.I|re.S) #失败print(res)ress = (' 因为match是从头开始匹配的print(ress) resss = ('href=".*?"',text,re.I|re.S) #对
通过结果可以看出Match和search得到的是正则表达式匹配对象提取结果需要使⽤特定函数Group () 匹配的正则字符串Groups() 返回包含字符串元组(为什么⽤元祖?因为元祖展⽰⼀个⼀个迭代,占⽤内存⼩)如:resss = ('href="(.*?)"',text,re.I|re.S) #对
在string中进⾏搜索print(resss)print(())print(())结果:< object; span=(3, 23), match='href=""'>href=
('',) #groups3).findall在string中查找所有 匹配成功的组, 即⽤括号括起来的部分。返回list对象,每个list item是由每个匹配的所有组组成的list。4).finditer在string中查找所有 匹配成功的字符串, 返回iterator,每个item是⼀个Match object。5).re,compile()提前建⽴⼀个匹配模式,可复⽤如:tmp = e('href=".*?"',re.I|re.S)print((text).group())输出:href=那么你也可以利⽤findall()匹配多个:例:import retext = '百度⼀下' '跳转'tmp = e('href=".*?"',re.I|re.S) #fuyongprint(l(text))输出:['href=""', 'href=""']6).()使⽤正则替换字符串我们可以⽤Python⾃带的replace或者translate解决,⼀般不常⽤例如:这⾥就是讲href替换为urlimport retext = '百度⼀下' '跳转'res = ("href",'url',text,re.I|re.S)print(res)输出: 百度⼀下跳转注:正则表达式还有很多,感兴趣的读者可以深⼊了解。⾯试常考:⽤正则表达式匹配邮件地址,ip地址,⼿机号码等5.4Python操作xpath1)安装模块⽅法:Pip install lxmlXPath 是⼀门在 XML ⽂档中查找信息的语⾔。XPath 可⽤来在 XML ⽂档中对元素和属性进⾏遍历。XPath 是 W3C XSLT 标准的主要元素,并且 XQuery 和 XPointer 都构建于 XPath 表达之上。2)XPath常⽤规则:表达式 描述nodename 选取此节点的所有⼦节点。/ 从根节点选取。// 从匹配选择的当前节点选择⽂档中的节点,⽽不考虑它们的位置。. 选取当前节点。… 选取当前节点的⽗节点。@ 选取属性。.CONTAINS() //DIV[CONTAINS(@ID,IN’)].TEXT() //a[text()=‘baidu’].STARTS-WITH() //div[starts-with(@id,‘in’)].NOT() //input[not(contains(@clas,a))]⽰例如下:对于多属性的标签,可以使⽤以上两种⽅法提取⾥边⽂字,当然提取标签⾥的属性,⽐如href(result)from lxml import etreetext = """
解析百度搜索页⾯#import requestsfrom lxml import etreedef get_html(): url = "/s?ie=utf-8&f=8&rsv_bp=1&ch=1&tn=25017023_6_dg&wd=%E9%98%BF%E9%87%8C%E5%B7%B4%E5%B7%B4&oq=Syntax%2526gt%253Brror%253A%2520invalid%2520syntax&rsv_pq=f02201a00002574e&rsv_t=902a2cbzt5E3YhY6KEiSSShOZRUS20hdRxLG%2F1ua661Acg21E%2BfZp8ENRLHoUGKs9BmZSg&rqlang=cn&rsv_enter=1&rsv_dl=tb&rsv_sug3=2&rsv_sug2=0&inputT=2168&rsv_sug4=3420" html = (url) if _code == 200: return get_content(html) else: print("get html error")def get_content(html): #ng="utf-8" #print() soup = () elements = ('//div[@id="content_left"]//div[starts-with(@class,"result")]') for e in elements: title = ('h3/a/text()') print("".join(title)) try: link = ('h3/a/@href')[0] print(link) except: print("no link") else: print("error")if __name__ == '__main__': get_html()#xpath
解析博客"/Amy-is-a-fish-yeah/p/"#import requestsfrom lxml import etreedef get_html(): url = "/Amy-is-a-fish-yeah/p/" html = (url) if _code == 200: return get_content(html) else: print("get html error")def get_content(html): ng="utf-8" #print() soup = () elements = ('//div[@class="post"]//div[@id="cnblogs_post_body"]/p/text()') new = ("".join(elements)) print(new)if __name__ == '__main__': get_html()
发布者:admin,转转请注明出处:http://www.yc00.com/web/1687982312a63492.html
评论列表(0条)