3.非结构化数据与结构化数据提取weihu

一般来讲对我们而言,需要抓取的是某个网站或者某个应用的内容,提取有用的价值。内容一般分为两部分,非结构化的数据和结构化的数据。

实际上爬虫一共就四个主要步骤:

我们在昨天的案例里实际上省略了第3步,也就是"取"的步骤。因为我们down下了的数据是全部的网页,这些数据很庞大并且很混乱,大部分的东西使我们不关心的,因此我们需要将之按我们的需要过滤和匹配出来。

那么对于文本的过滤或者规则的匹配,最强大的就是正则表达式,是Python爬虫世界里必不可少的神兵利器。

正则表达式,又称规则表达式,通常被用来检索、替换那些符合某个模式(规则)的文本。

正则表达式是对字符串操作的一种逻辑公式,就是用事先定义好的一些特定字符、及这些特定字符的组合,组成一个“规则字符串”,这个“规则字符串”用来表达对字符串的一种过滤逻辑。

给定一个正则表达式和另一个字符串,我们可以达到如下的目的:

在Python中,我们可以使用内置的re模块来使用正则表达式。

有一点需要特别注意的是,正则表达式使用对特殊字符进行转义,所以如果我们要使用原始字符串,只需加一个r前缀,示例:

r'chuanzhiboke\t\.\tpython'

使用compile()函数将正则表达式的字符串形式编译为一个Pattern对象通过Pattern对象提供的一系列方法对文本进行匹配查找,获得匹配结果,一个Match对象。最后使用Match对象提供的属性和方法获得信息,根据需要进行其他的操作

compile函数用于编译正则表达式,生成一个Pattern对象,它的一般使用形式如下:

importre#将正则表达式编译成Pattern对象pattern=re.compile(r'\d+')

在上面,我们已将一个正则表达式编译成Pattern对象,接下来,我们就可以利用pattern的一系列方法对文本进行匹配查找了。

Pattern对象的一些常用方法主要有:

match方法用于查找字符串的头部(也可以指定起始位置),它是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果。它的一般使用形式如下:

match(string[,pos[,endpos]])

其中,string是待匹配的字符串,pos和endpos是可选参数,指定字符串的起始和终点位置,默认值分别是0和len(字符串长度)。因此,当你不指定pos和endpos时,match方法默认匹配字符串的头部。

当匹配成功时,返回一个Match对象,如果没有匹配上,则返回None。

>>>importre>>>pattern=re.compile(r'\d+')#用于匹配至少一个数字>>>m=pattern.match('one12twothree34four')#查找头部,没有匹配>>>printmNone>>>m=pattern.match('one12twothree34four',2,10)#从'e'的位置开始匹配,没有匹配>>>printmNone>>>m=pattern.match('one12twothree34four',3,10)#从'1'的位置开始匹配,正好匹配>>>printm#返回一个Match对象<_sre.SRE_Matchobjectat0x10a42aac0>>>>m.group(0)#可省略0'12'>>>m.start(0)#可省略03>>>m.end(0)#可省略05>>>m.span(0)#可省略0(3,5)在上面,当匹配成功时返回一个Match对象,其中:

再看看一个例子:

>>>importre>>>pattern=re.compile(r'([a-z]+)([a-z]+)',re.I)#re.I表示忽略大小写>>>m=pattern.match('HelloWorldWideWeb')>>>printm#匹配成功,返回一个Match对象<_sre.SRE_Matchobjectat0x10bea83e8>>>>m.group(0)#返回匹配成功的整个子串'HelloWorld'>>>m.span(0)#返回匹配成功的整个子串的索引(0,11)>>>m.group(1)#返回第一个分组匹配成功的子串'Hello'>>>m.span(1)#返回第一个分组匹配成功的子串的索引(0,5)>>>m.group(2)#返回第二个分组匹配成功的子串'World'>>>m.span(2)#返回第二个分组匹配成功的子串(6,11)>>>m.groups()#等价于(m.group(1),m.group(2),...)('Hello','World')>>>m.group(3)#不存在第三个分组Traceback(mostrecentcalllast):File"",line1,inIndexError:nosuchgroup------------------------------------------------------------------------------------------------------search方法search方法用于查找字符串的任何位置,它也是一次匹配,只要找到了一个匹配的结果就返回,而不是查找所有匹配的结果,它的一般使用形式如下:

search(string[,pos[,endpos]])

其中,string是待匹配的字符串,pos和endpos是可选参数,指定字符串的起始和终点位置,默认值分别是0和len(字符串长度)。

让我们看看例子:

>>>importre>>>pattern=re.compile('\d+')>>>m=pattern.search('one12twothree34four')#这里如果使用match方法则不匹配>>>m<_sre.SRE_Matchobjectat0x10cc03ac0>>>>m.group()'12'>>>m=pattern.search('one12twothree34four',10,30)#指定字符串区间>>>m<_sre.SRE_Matchobjectat0x10cc03b28>>>>m.group()'34'>>>m.span()(13,15)再来看一个例子:

#-*-coding:utf-8-*-importre#将正则表达式编译成Pattern对象pattern=re.compile(r'\d+')#使用search()查找匹配的子串,不存在匹配的子串时将返回None#这里使用match()无法成功匹配m=pattern.search('hello123456789')ifm:#使用Match获得分组信息print'matchingstring:',m.group()#起始位置和结束位置print'position:',m.span()执行结果:matchingstring:123456position:(6,12)------------------------------------------------------------------------------------------------------findall方法上面的match和search方法都是一次匹配,只要找到了一个匹配的结果就返回。然而,在大多数时候,我们需要搜索整个字符串,获得所有匹配的结果。

findall方法的使用形式如下:

findall(string[,pos[,endpos]])

findall以列表形式返回全部能匹配的子串,如果没有匹配,则返回一个空列表。

看看例子:

importrepattern=re.compile(r'\d+')#查找数字result1=pattern.findall('hello123456789')result2=pattern.findall('one1two2three3four4',0,10)printresult1printresult2执行结果:

['123456','789']['1','2']再先看一个栗子:

#re_test.pyimportre#re模块提供一个方法叫compile模块,提供我们输入一个匹配的规则#然后返回一个pattern实例,我们根据这个规则去匹配字符串pattern=re.compile(r'\d+\.\d*')#通过partten.findall()方法就能够全部匹配到我们得到的字符串result=pattern.findall("123.141593,'bigcat',232312,3.15")#findall以列表形式返回全部能匹配的子串给resultforiteminresult:printitem运行结果:

123.1415933.15------------------------------------------------------------------------------------------------------finditer方法finditer方法的行为跟findall的行为类似,也是搜索整个字符串,获得所有匹配的结果。但它返回一个顺序访问每一个匹配结果(Match对象)的迭代器。

#-*-coding:utf-8-*-importrepattern=re.compile(r'\d+')result_iter1=pattern.finditer('hello123456789')result_iter2=pattern.finditer('one1two2three3four4',0,10)printtype(result_iter1)printtype(result_iter2)print'result1...'form1inresult_iter1:#m1是Match对象print'matchingstring:{},position:{}'.format(m1.group(),m1.span())print'result2...'form2inresult_iter2:print'matchingstring:{},position:{}'.format(m2.group(),m2.span())执行结果:

result1...matchingstring:123456,position:(6,12)matchingstring:789,position:(13,16)result2...matchingstring:1,position:(3,4)matchingstring:2,position:(7,8)------------------------------------------------------------------------------------------------------split方法split方法按照能够匹配的子串将字符串分割后返回列表,它的使用形式如下:

split(string[,maxsplit])

其中,maxsplit用于指定最大分割次数,不指定将全部分割。

importrep=re.compile(r'[\s\,\;]+')printp.split('a,b;;cd')执行结果:

['a','b','c','d']------------------------------------------------------------------------------------------------------sub方法sub方法用于替换。它的使用形式如下:

sub(repl,string[,count])

其中,repl可以是字符串也可以是一个函数:

importrep=re.compile(r'(\w+)(\w+)')#\w=[A-Za-z0-9]s='hello123,hello456'printp.sub(r'helloworld',s)#使用'helloworld'替换'hello123'和'hello456'printp.sub(r'\2\1',s)#引用分组deffunc(m):return'hi'+''+m.group(2)printp.sub(func,s)printp.sub(func,s,1)#最多替换一次执行结果:

helloworld,helloworld123hello,456hellohi123,hi456hi123,hello456------------------------------------------------------------------------------------------------------匹配中文在某些情况下,我们想匹配文本中的汉字,有一点需要注意的是,中文的unicode编码范围主要在[u4e00-u9fa5],这里说主要是因为这个范围并不完整,比如没有包括全角(中文)标点,不过,在大部分情况下,应该是够用的。

假设现在想把字符串title=u'你好,hello,世界'中的中文提取出来,可以这么做:

importretitle=u'你好,hello,世界'pattern=re.compile(ur'[\u4e00-\u9fa5]+')result=pattern.findall(title)printresult注意到,我们在正则表达式前面加上了两个前缀ur,其中r表示使用原始字符串,u表示是unicode字符串。

执行结果:

[u'\u4f60\u597d',u'\u4e16\u754c']

这里采用的是贪婪模式。在匹配到第一个“

”时已经可以使整个表达式匹配成功,但是由于采用的是贪婪模式,所以仍然要向右尝试匹配,查看是否还有更长的可以成功匹配的子串。匹配到第二个“
”后,向右再没有可以成功匹配的子串,匹配结束,匹配结果为“
test1
bb
test2

正则表达式二采用的是非贪婪模式,在匹配到第一个“

”时使整个表达式匹配成功,由于采用的是非贪婪模式,所以结束匹配,不再向右尝试,匹配结果为“
test1
”。

正则表达式测试网址

现在拥有了正则表达式这把神兵利器,我们就可以进行对爬取到的全部网页源代码进行筛选了。

打开之后,不难看到里面一个一个灰常有内涵的段子,当你进行翻页的时候,注意url地址的变化:

这样我们的url规律找到了,要想爬取所有的段子,只需要修改一个参数即可。下面我们就开始一步一步将所有的段子爬取下来吧。

这里我们统一定义一个类,将url请求作为一个成员方法处理。

我们创建一个文件,叫duanzi_spider.py

然后定义一个Spider类,并且添加一个加载页面的成员方法

以上的loadPage的实现体想必大家应该很熟悉了,需要注意定义python类的成员方法需要额外添加一个参数self.

if__name__=='__main__':"""======================内涵段子小爬虫======================"""print'请按下回车开始'raw_input()#定义一个Spider对象mySpider=Spider()mySpider.loadpage(1)

注意:对于每个网站对中文的编码各自不同,所以html.decode(‘gbk’)的写法并不是通用写法,根据网站的编码而异

这样我们再次执行以下duanzi_spider.py,会发现之前的中文乱码可以正常显示了。

接下来我们已经得到了整个页面的数据。但是,很多内容我们并不关心,所以下一步我们需要进行筛选。如何筛选,就用到了上一节讲述的正则表达式。

importre我们需要一个匹配规则:我们可以打开内涵段子的网页,鼠标点击右键“查看源代码”你会惊奇的发现,我们需要的每个段子的内容都是在一个

标签中,而且每个div都有一个属性class="f18mb20"

所以,我们只需要匹配到网页中所有

的数据就可以了。

Power@PowerMac~$pythonduanzi_spider.py我们第一页的全部段子,不包含其他信息全部的打印了出来。defprintOnePage(self,item_list,page):"""@brief处理得到的段子列表@paramitem_list得到的段子列表@parampage处理第几页"""print"*******第%d页爬取完毕...*******"%pageforiteminitem_list:print"================"item=item.replace("

","").replace("

","").replace("
","")printitem

defwriteToFile(self,text):'''@brief将数据追加写进文件中@paramtext文件内容'''myFile=open("./duanzi.txt",'a')#追加形式打开文件myFile.write(text)myFile.write("-----------------------------------------------------")myFile.close()然后我们将print的语句改成writeToFile(),当前页面的所有段子就存在了本地的MyStory.txt文件中。defprintOnePage(self,item_list,page):'''@brief处理得到的段子列表@paramitem_list得到的段子列表@parampage处理第几页'''print"*******第%d页爬取完毕...*******"%pageforiteminitem_list:#print"================"item=item.replace("

","").replace("

","").replace("
","")#printitemself.writeToFile(item)

defdoWork(self):'''让爬虫开始工作'''whileself.enable:try:item_list=self.loadPage(self.page)excepturllib2.URLError,e:printe.reasoncontinue#对得到的段子item_list处理self.printOnePage(item_list,self.page)self.page+=1#此页处理完毕,处理下一页print"按回车继续..."print"输入quit退出"command=raw_input()if(command=="quit"):self.enable=Falsebreak

以上便是一个非常精简使用的小爬虫程序,使用起来很是方便,如果想要爬取其他网站的信息,只需要修改其中某些参数和一些细节就行了。

有同学说,我正则用的不好,处理HTML文档很累,有没有其他的方法?

有!那就是XPath,我们可以先将HTML文件转换成XML文档,然后用XPath查找HTML节点或元素。

EverydayItalianGiadaDeLaurentiis200530.00HarryPotterJK.Rowling200529.99XQueryKickStartJamesMcGovernPerBothnerKurtCagleJamesLinnVaidyanathanNagarajan200349.99LearningXMLErikT.Ray200339.95

HTMLDOM定义了访问和操作HTML文档的标准方法,以树结构方式表达HTML文档。

每个元素以及属性都有一个父。

下面是一个简单的XML例子中,book元素是title、author、year以及price元素的父:

HarryPotterJK.Rowling200529.99

元素节点可有零个、一个或多个子。

在下面的例子中,title、author、year以及price元素都是book元素的子:

拥有相同的父的节点

在下面的例子中,title、author、year以及price元素都是同胞:

某节点的父、父的父,等等。

在下面的例子中,title元素的先辈是book元素和bookstore元素:

HarryPotterJK.Rowling200529.99

某个节点的子,子的子,等等。

在下面的例子中,bookstore的后代是book、title、author、year以及price元素:

XPath(XMLPathLanguage)是一门在XML文档中查找信息的语言,可用来在XML文档中对元素和属性进行遍历。

XPath使用路径表达式来选取XML文档中的节点或者节点集。这些路径表达式和我们在常规的电脑文件系统中看到的表达式非常相似。

下面列出了最常用的路径表达式:

在下面的表格中,我们已列出了一些路径表达式以及表达式的结果:

谓语用来查找某个特定的节点或者包含某个指定的值的节点,被嵌在方括号中。

在下面的表格中,我们列出了带有谓语的一些路径表达式,以及表达式的结果:

XPath通配符可用来选取未知的XML元素。

在下面的表格中,我们列出了一些路径表达式,以及这些表达式的结果:

通过在路径表达式中使用“|”运算符,您可以选取若干个路径。

实例

下面列出了可用在XPath表达式中的运算符:

lxml是一个HTML/XML的解析器,主要的功能是如何解析和提取HTML/XML数据。

lxml和正则一样,也是用C实现的,是一款高性能的PythonHTML/XML解析器,我们可以利用之前学习的XPath语法,来快速的定位特定元素以及节点信息。

需要安装C语言库,可使用pip安装:pipinstalllxml(或通过wheel方式安装)

我们利用它来解析HTML代码,简单示例:

输出结果:

lxml可以自动修正html代码,例子里不仅补全了li标签,还添加了body,html标签。

除了直接读取字符串,lxml还支持从文件里读取内容。我们新建一个hello.html文件:

再利用etree.parse()方法来读取文件。

#lxml_parse.pyfromlxmlimportetree#读取外部文件hello.htmlhtml=etree.parse('./hello.html')result=etree.tostring(html,pretty_print=True)print(result)

输出结果与之前相同:

#xpath_li.pyfromlxmlimportetreehtml=etree.parse('hello.html')printtype(html)#显示etree.parse()返回类型result=html.xpath('//li')printresult#打印

  • 标签的元素集合printlen(result)printtype(result)printtype(result[0])

    [,,,,]5

    #xpath_li.pyfromlxmlimportetreehtml=etree.parse('hello.html')result=html.xpath('//li/@class')printresult

    运行结果

    ['item-0','item-1','item-inactive','item-1','item-0']

    []

    #xpath_li.pyfromlxmlimportetreehtml=etree.parse('hello.html')#result=html.xpath('//li/span')#注意这么写是不对的:#因为/是用来获取子元素的,而并不是

  • 的子元素,所以,要用双斜杠result=html.xpath('//li//span')printresult

    []

    #xpath_li.pyfromlxmlimportetreehtml=etree.parse('hello.html')result=html.xpath('//li/a//@class')printresult

    ['blod']

    ['link5.html']

    #xpath_li.pyfromlxmlimportetreehtml=etree.parse('hello.html')result=html.xpath('//li[last()-1]/a')#text方法可以获取元素内容printresult[0].text

    fourthitem

    #xpath_li.pyfromlxmlimportetreehtml=etree.parse('hello.html')result=html.xpath('//*[@class="bold"]')#tag方法可以获取标签名printresult[0].tag

    span

    案例:使用XPath的爬虫现在我们用XPath来做一个简单的爬虫,我们尝试爬取某个贴吧里的所有帖子,并且将该这个帖子里每个楼层发布的图片下载到本地。

    和lxml一样,BeautifulSoup也是一个HTML/XML的解析器,主要的功能也是如何解析和提取HTML/XML数据。

    BeautifulSoup3目前已经停止开发,推荐现在的项目使用BeautifulSoup4。使用pip安装即可:pipinstallbeautifulsoup4

    首先必须要导入bs4库

    运行结果:

    BeautifulSoup将复杂HTML文档转换成一个复杂的树形结构,每个节点都是Python对象,所有对象可以归纳为4种:

    Tag通俗点讲就是HTML中的一个个标签,例如:

    上面的titleheadap等等HTML标签加上里面包括的内容就是Tag,那么试着使用BeautifulSoup来获取Tags:

    我们可以利用soup加标签名轻松地获取这些标签的内容,这些对象的类型是bs4.element.Tag。但是注意,它查找的是在所有内容中的第一个符合要求的标签。如果要查询所有的标签,后面会进行介绍。

    printsoup.name#[document]#soup对象本身比较特殊,它的name即为[document]printsoup.head.name#head#对于其他内部标签,输出的值便为标签本身的名称printsoup.p.attrs#{'class':['title'],'name':'dromouse'}#在这里,我们把p标签的所有属性打印输出了出来,得到的类型是一个字典。printsoup.p['class']#soup.p.get('class')#['title']#还可以利用get方法,传入属性的名称,二者是等价的soup.p['class']="newClass"printsoup.p#可以对这些属性和内容等等进行修改#TheDormouse'sstory

    delsoup.p['class']#还可以对这个属性进行删除printsoup.p#TheDormouse'sstory

    既然我们已经得到了标签的内容,那么问题来了,我们要想获取标签内部的文字怎么办呢?很简单,用.string即可,例如

    printsoup.p.string#TheDormouse'sstoryprinttype(soup.p.string)#In[13]:

    BeautifulSoup对象表示的是一个文档的内容。大部分时候,可以把它当作Tag对象,是一个特殊的Tag,我们可以分别获取它的类型,名称,以及属性来感受一下

    printtype(soup.name)#printsoup.name#[document]printsoup.attrs#文档本身的属性为空#{}

    Comment对象是一个特殊类型的NavigableString对象,其输出的内容不包括注释符号。

    a标签里的内容实际上是注释,但是如果我们利用.string来输出它的内容时,注释符号已经去掉了。

    tag的.content属性可以将tag的子节点以列表的方式输出

    printsoup.head.contents#[TheDormouse'sstory]

    输出方式为列表,我们可以用列表索引来获取它的某一个元素

    printsoup.head.contents[0]#TheDormouse'sstory

    它返回的不是一个list,不过我们可以通过遍历获取所有子节点。

    我们打印输出.children看一下,可以发现它是一个list生成器对象

    printsoup.head.children#forchildinsoup.body.children:printchild

    结果:

    .contents和.children属性仅包含tag的直接子节点,.descendants属性可以对所有tag的子孙节点进行递归循环,和children类似,我们也需要遍历获取其中的内容。

    forchildinsoup.descendants:printchild

    如果tag只有一个NavigableString类型子节点,那么这个tag可以使用.string得到子节点。如果一个tag仅有一个子节点,那么这个tag也可以使用.string方法,输出结果与当前唯一子节点的.string结果相同。

    通俗点说就是:如果一个标签里面没有标签了,那么.string就会返回标签里面的内容。如果标签里面只有唯一的一个标签了,那么.string也会返回最里面的内容。例如:

    printsoup.head.string#TheDormouse'sstoryprintsoup.title.string#TheDormouse'sstory

    name参数可以查找所有名字为name的tag,字符串对象会被自动忽略掉

    最简单的过滤器是字符串.在搜索方法中传入一个字符串参数,BeautifulSoup会查找与字符串完整匹配的内容,下面的例子用于查找文档中所有的标签:

    如果传入正则表达式作为参数,BeautifulSoup会通过正则表达式的match()来匹配内容.下面例子中找出所有以b开头的标签,这表示和标签都应该被找到

    importrefortaginsoup.find_all(re.compile("^b")):print(tag.name)#body#b

    如果传入列表参数,BeautifulSoup会将与列表中任一元素匹配的内容返回.下面代码找到文档中所有标签和标签:

    通过text参数可以搜搜文档中的字符串内容,与name参数的可选值一样,text参数接受字符串,正则表达式,列表

    soup.find_all(text="Elsie")#[u'Elsie']soup.find_all(text=["Tillie","Elsie","Lacie"])#[u'Elsie',u'Lacie',u'Tillie']soup.find_all(text=re.compile("Dormouse"))[u"TheDormouse'sstory",u"TheDormouse'sstory"]

    这就是另一种与find_all方法有异曲同工之妙的查找方法.

    组合查找即和写class文件时,标签名与类名、id名进行的组合原理是一样的,例如查找p标签中,id等于link1的内容,二者需要用空格分开

    直接子标签查找,则使用>分隔

    printsoup.select("head>title")#[TheDormouse'sstory]

    查找时还可以加入属性元素,属性需要用中括号括起来,注意属性和标签属于同一节点,所以中间不能加空格,否则会无法匹配到。

    同样,属性仍然可以与上述查找方式组合,不在同一节点的空格隔开,同一节点的不加空格

    以上的select方法返回的结果都是列表形式,可以遍历形式输出,然后用get_text()方法来获取它的内容。

    soup=BeautifulSoup(html,'lxml')printtype(soup.select('title'))printsoup.select('title')[0].get_text()fortitleinsoup.select('title'):printtitle.get_text()

    数据提取之JSON与JsonPATHJSON(JavaScriptObjectNotation)是一种轻量级的数据交换格式,它使得人们很容易的进行阅读和编写。同时也方便了机器进行解析和生成。适用于进行数据交互的场景,比如网站前台与后台之间的数据交互。

    JSON和XML的比较可谓不相上下。

    Python2.7中自带了JSON模块,直接importjson就可以使用了。

    json简单说就是javascript中的对象和数组,所以这两种结构就是对象和数组两种结构,通过这两种结构可以表示各种复杂的结构

    1.对象:对象在js中表示为{}括起来的内容,数据结构为{key:value,key:value,...}的键值对的结构,在面向对象的语言中,key为对象的属性,value为对应的属性值,所以很容易理解,取值方法为对象.key获取属性值,这个属性值的类型可以是数字、字符串、数组、对象这几种。

    2.数组:数组在js中是中括号[]括起来的内容,数据结构为["Python","javascript","C++",...],取值方式和所有语言中一样,使用索引获取,字段值的类型可以是数字、字符串、数组、对象几种。

    json模块提供了四个功能:dumps、dump、loads、load,用于字符串和python数据类型间进行转换。

    把Json格式字符串解码转换成Python对象从json到python的类型转化对照如下:

    实现python类型转化为json字符串,返回一个str对象把一个Python对象编码转换成Json字符串

    从python原始类型向json类型的转化对照如下:

    #json_dumps.pyimportjsonimportchardetlistStr=[1,2,3,4]tupleStr=(1,2,3,4)dictStr={"city":"北京","name":"大猫"}json.dumps(listStr)#'[1,2,3,4]'json.dumps(tupleStr)#'[1,2,3,4]'#注意:json.dumps()序列化时默认使用的ascii编码#添加参数ensure_ascii=False禁用ascii编码,按utf-8编码#chardet.detect()返回字典,其中confidence是检测精确度json.dumps(dictStr)#'{"city":"\\u5317\\u4eac","name":"\\u5927\\u5218"}'chardet.detect(json.dumps(dictStr))#{'confidence':1.0,'encoding':'ascii'}printjson.dumps(dictStr,ensure_ascii=False)#{"city":"北京","name":"大刘"}chardet.detect(json.dumps(dictStr,ensure_ascii=False))#{'confidence':0.99,'encoding':'utf-8'}

    chardet是一个非常优秀的编码识别模块,可通过pip安装

    将Python内置类型序列化为json对象后写入文件

    #json_dump.pyimportjsonlistStr=[{"city":"北京"},{"name":"大刘"}]json.dump(listStr,open("listStr.json","w"),ensure_ascii=False)dictStr={"city":"北京","name":"大刘"}json.dump(dictStr,open("dictStr.json","w"),ensure_ascii=False)

    读取文件中json形式的字符串元素转化成python类型

    #json_load.pyimportjsonstrList=json.load(open("listStr.json"))printstrList#[{u'city':u'\u5317\u4eac'},{u'name':u'\u5927\u5218'}]strDict=json.load(open("dictStr.json"))printstrDict#{u'city':u'\u5317\u4eac',u'name':u'\u5927\u5218'}

    JsonPath是一种信息抽取类库,是从JSON文档中抽取指定信息的工具,提供多种语言实现版本,包括:Javascript,Python,PHP和Java。

    JsonPath对于JSON来说,相当于XPATH对于XML。

    安装方法:点击DownloadURL链接下载jsonpath,解压之后执行pythonsetup.pyinstall

    Json结构清晰,可读性高,复杂度低,非常容易匹配,下表中对应了XPath的用法。

    json.loads()是把Json格式字符串解码转换成Python对象,如果在json.loads的时候出错,要注意被解码的Json字符的编码。

    如果传入的字符串的编码不是UTF-8的话,需要指定字符编码的参数encoding

    dataDict=json.loads(jsonStrGBK);```pythondataJsonStrUni=dataJsonStr.decode("GB2312");dataDict=json.loads(dataJsonStrUni,encoding="GB2312");

    ##字符串编码转换这是中国程序员最苦逼的地方,什么乱码之类的几乎都是由汉字引起的。其实编码问题很好搞定,只要记住一点:####任何平台的任何编码都能和Unicode互相转换UTF-8与GBK互相转换,那就先把UTF-8转换成Unicode,再从Unicode转换成GBK,反之同理。```python#这是一个UTF-8编码的字符串utf8Str="你好地球"#1.将UTF-8编码的字符串转换成Unicode编码unicodeStr=utf8Str.decode("UTF-8")#2.再将Unicode编码格式字符串转换成GBK编码gbkData=unicodeStr.encode("GBK")#1.再将GBK编码格式字符串转化成UnicodeunicodeStr=gbkData.decode("gbk")#2.再将Unicode编码格式字符串转换成UTF-8utf8Str=unicodeStr.encode("UTF-8")

    decode的作用是将其他编码的字符串转换成Unicode编码

    encode的作用是将Unicode编码转换成其他编码的字符串

    一句话:UTF-8是对Unicode字符集进行编码的一种编码方式

    案例要求参考上一个糗事百科单进程案例

    Queue是python中的标准库,可以直接importQueue引用;队列是线程间最常用的交换数据的形式

    python下多线程的思考

    对于资源,加锁是个重要的环节。因为python原生的list,dict等,都是notthreadsafe的。而Queue,是线程安全的,因此在满足使用条件下,建议使用队列

  • THE END
    1.数据架构设计与优化策略的深度探索天翼云开发者社区2.1 数据模型设计 数据模型是数据架构的核心组成部分,它描述了数据的结构、关系和约束条件。在数据模型设计中,需要采用合适的数据建模方法和技术,如实体-关系模型(ER模型)、对象-关系模型(ORM模型)等,根据业务需求和数据特点,构建清晰、准确的数据模型。 https://www.ctyun.cn/developer/article/624399106633797
    2.非结构化数据怎么治理?最近遇到几个项目,都跟非结构化数据脱不开关系。老彭刚毕业的时候,做的是数据库的活儿,那都是结构化数据。后来有了hadoop技术,可以用来处理物联网、互联网的半结构化数据。真正做非结构化的场景还是比较少的,大多是在项目中选取一两个点给意思意思一下。https://www.niaogebiji.com/article-139650-1.html
    3.非结构化数据的定义及处理方法为解决上面两种方式的缺点,利用其所长,最新的非结构化数据存储技术在磁盘格式、网络协议、空间管理、重做和撤销格式、缓冲区缓存以及智能的I/O子系统等方面发生重大转变,在保证了文件数据的性能的同时,还保留了数据库的优势。较有代表性的就是OracleSecureFiles非结构化数据存储方式。https://blog.csdn.net/weixin_52189060/article/details/115489159
    4.非结构化数据怎么存?——开源对象存储方案介绍但是构建一个企业级的数据湖(包括结构化和非结构化数据)已经成为了越来越多公司的目标。那么Hadoop还能满足我们的要求吗?还是我们需要更多的选择? 存储方案 如图所示,底层存储大体可以分为四类。对象存储(Object Storage),NoSQL 数据库(NoSQL Sources),关系型数据库(RDBMS Storage),大数据(Hadoop)。 对于大量的数据https://cloud.tencent.com/developer/article/1882011
    5.大数据基础术语精粹来袭NoSQL数据库的产生就是为了解决大规模数据集合多重数据种类带来的挑战,尤其是大数据应用难题。 十三:结构化数据 结构化数据(即行数据,存储在数据库里,可以用二维表结构来逻辑表达实现的数据)而言,不方便用数据库二维逻辑表来表现的数据即称为非结构化数据,包括所有格式的办公文档、文本、图片、标准通用标记语言下的http://www.mudan.gov.cn/2c908084831c4eb30183205259ac001f/2c908084831c4eb3018320df837d0020/1669185201282129920.html
    6.非结构化数据分析技术非结构化数据主要包括非结构化数据是数据结构不规则或者说是不完整,没有预设的数据模型或者结构,不便使用数据库、模型及标准的数据接口表现的数据,包括所有格式的文本、图片、各类报表、图像、音频、视频数据等。 计算机信息化系统中的数据分为结构化数据和非结构化数据。非结构化数据的形式非常多样,标准也具有多样性(即标准不确定),同时在https://blog.51cto.com/u_16099165/6757640
    7.非结构化数据如何挖掘帆软数字化转型知识库数据隐私问题涉及用户数据的安全和保护,如何在挖掘数据的同时保护用户隐私是一个重要课题。未来,随着人工智能和大数据技术的发展,非结构化数据挖掘将变得更加智能和高效。新算法和新技术的出现将推动非结构化数据挖掘的发展,解决现有的挑战和问题,提高数据挖掘的准确性和效率。企业应积极关注和应用最新的技术和方法,充分https://www.fanruan.com/blog/article/611442/
    8.《DAMADMBOK2》读书笔记第9章文件和内容管理内容管理在网站和门户中尤为重要,但基于关键字的索引和基于分类的组织方法可以跨技术平台应用。当在整个企业范围内进行内容管理时,称之为企业内容管理(ECM)。 内容元数据 P232 元数据对于管理非结构化数据至关重要,无论是传统上认为的内容和文件,还是现在理解的“大数据”。如果没有元数据,就无法对内容进行编目和组https://www.jianshu.com/p/fa34d269374b
    9.行政管理论文15篇生活化教学可以帮助学生以社会生活实践为视觉,探究社会生活实践的种种样式所蕴含的行政管理,涉及日常的行政环境、职能、组织、领导、人事、财政、信息、政策过程及分析、伦理、法治、监督、危机、后勤、绩效和改革发展等各个环节,从中挖掘行政管理环节问题、分析问题原因和找出解决问题的方法,这对于不断培养大学生的行政https://www.ruiwen.com/lunwen/6220159.html
    10.数据架构:大数据数据仓库以及DataVault非结构化数据可以进一步划分成两种基本的数据形式:重复型非结构化数据和非重复型非结构化数据。与企业数据的划分一样,非结构化数据的细分方式也有很多种。这里给出的只是其中一种细分非结构化数据的方法。图1.1.3展现了非结构化数据的这一细分方法。 重复型非结构化数据是指以同样的结构甚至同样的形态出现多次的数据https://www.ituring.com.cn/book/tupubarticle/11854
    11.什么是非结构化数据?我们所处理的数据分为三类,分别是规格化数据、半结构化数据以及非结构化数据,其中非结构化数据的定义为:呈现出不规则且无明显结构特征的数据。 -规格化数据:数据与字段相对应,数据以表格和数据集形式存在。 -半结构化数据:这种数据形态介于规格化数据和非结构化数据之间,方法是结合不明晰的规则来补足规格化数据的缺陷。https://www.filez.com/news/detail/faee08ab6bdc85c2d6216e4773bcc01f.html
    12.engineering):利用领域知识和现有数据,创造出新的特征,用于具体涵盖了结构化与非结构化、定量与定性数据的区分,数据清洗中的数据对齐、缺失值处理、异常值处理等方法,特征构造中的统计量构造、周期值、数据分桶、特征组合,特征选择的三种形式及多种具体方法,特征变换的标准化、归一化、区间缩放、非线性变换等,还讨论了离散变量处理和降维的多种方法,并在最后进行了总结。https://juejin.cn/post/6874516288149028872