python爬虫之数据提取、正则表达式、xml、XPath、etree、CSS选择器 BeautifulSoup4

1、页面解析和数据提取简介

(1)结构数据:先有的结构,再谈数据

        -JSON文件

              -JSON Path

              -转换成python类型进行操作(json类)

       -XML文件

              -转换成python类型(xmltodict)

              -XPath

              -CSS选择器

              -正则

(2)非结构化数据:先有数据,再谈结构

        -文本、电话号码、邮箱地址

                 -通常处理此类数据,使用正则表达式

        -Html文件

                 -正则

                 -XPath

                 -CSS选择器

2、正则表达式

(1)一套规则,可以在字符串文本中进行搜索替换等

在正则表达式中,可以对过滤到的字符串进行分组。分组使用圆括号的方式。

  1. group:和group(0)是等价的,返回的是整个满足条件的字符串。
  2. groups:返回的是里面的子组。索引从1开始。
  3. group(1):返回的是第一个子组,可以传入多个。

(2)-re的基本使用流程

'''
使用大致步骤:
1、compile函数将正则表达式的字符串变为一个pattern对象
2、通过pattern对象的一些方法对文本进行匹配,匹配结果是一个Match对象
3、用Match对象的方法对结果进行操纵
'''

import re
#\d表示以数字
#后面+号表示这个数字可以出现一次或者多次
s = r"\d+"  #r表示后面是原生字符串,后面不需要转义

#返回pattern对象
pattern = re.compile(s)

#返回一个match对象,后面的位置参数含义是从哪个位置开始查找,找到哪个位置结束
#默认找到一个匹配就返回
m = pattern.match("one12two34three56",3,10)

print(type(m))
#默认匹配从头部开始,所以此次结果为None
print(m)

print(m.group())
print(m.start(0))
print(m.end(0))
print(m.span(0))
运行:


12
3
5
(3, 5)

         -match的基本使用

'''
正则结果的match的使用案例
'''
import re

#以下正则分成了两个组,以小括号为单位
s = r'([a-z]+) ([a-z]+) ([a-z]+)'
pattern = re.compile(s,re.I) #re.I表示忽略大小写

m = pattern.match("Hello World wide web")

#group(0) 表示返回匹配成功的整个子串
s = m.group(0)
print(s)

a = m.span(0) #返回匹配成功整个子串的跨度
print(a)

#group(1)表示返回的第一个分组匹配成功的子串
s = m.group(1)
print(s)

a = m.span(1) #返回匹配成功的第一个子串的跨度
print(a)

s = m.groups() #等价于m.group(1),m.group(2)....
print(s)

运行:
Hello World wide
(0, 16)
Hello
(0, 5)
('Hello', 'World', 'wide')

(3)正则常用方法

-match:从开始位置开始查找,一次匹配

-search:从任何位置查找,一次匹配

-findall:全部匹配,返回列表

-finditer:全部匹配,返回迭代器

-split:分隔字符串,返回列表

-sub :替换     

'''
search
'''
import re

s = r'\d+'   #至少且只有一个数字
pattern = re.compile(s)  #编译
m = pattern.search("one12two34three56")
print(m.group())

#参数表明搜查的起始范围
m = pattern.search("one12two34three56",10,40)
print(m.group())

'''
findall
'''
import re
pattern = re.compile(r'\d+')
s = pattern.findall("i am 18 years old and 185 high")
print(s)

s = pattern.finditer("i am 18 years old and 185 high")
print(type(s))

for i in s:
    print(i.group())

运行:
12
56
['18', '185']

18
185

(4)匹配中文

-中文unicode范围主要是在[u4e00-u9fa5]

'''
中文unicode案例
'''
import re
hello = u'你好,世界'
pattern = re.compile(r'[\u4e00-\u9fa5]+')
m = pattern.findall(hello)
print(m)
运行:
['你好', '世界']

 (5)贪婪与非贪婪模式

-贪婪模式:在整个表达式匹配成功的前提下,尽可能多的匹配

-非贪婪模式:xxxxxx,尽可能少的匹配

-python里面数量词默认是贪婪模式

-例如:

         -查找文本abbbbccc

         -re是ab*

         -贪婪模式:abbbb

         -非贪婪模式:a

3、xml 为了传输数据

-XML(ExtensibleMarkupLanguage)

-http://www.w3school.com.cn/xml/index.asp

-概念:父节点、子节点、先辈节点、兄弟节点、后代节点

>

    
        Everyday Italian
        Gidada De
        2018
        23
    

    
        Running
        Klaus Kuka
        2010
        43
    

    
        Python is Python
        Food War
        2008
        83
    

4、XPath

(1)XPath(XML Path Language),是一门在XML文档中查找信息的语言

-官方文档:http://www.w3school.com.cn/xpath/index.asp

-XPath开发工具

        -开元的XPath表达式工具:XMLQuire

        -chrome插件:Xpath Helper

        -Firefox插件:XPath CHecker

(2)常用路径表达式

-nodename:选取此节点的所有子节点

- / :从根节点开始选

- // :选取元素,而不考虑元素的具体位置

- . :当前节点

- @ :选取属性

(3)案例:

-bookstore:选取bookstore下的所有子节点

-/bookstore:选取根元素

-bookstore/book:选取bookstore的所有为book的子元素

- //book:选取book子元素

- //@lang:选取名称为lNG的所有属性

(4)谓语(Predicates)

-谓语用来查找某个特定的节点,被镶嵌在方括号中

-/bookstore/book[1]:选取第一个属于bookstore下叫book的元素

-/bookstore/book[last()]:选取最后一个属于bookstore下叫book的元素

-/bookstore/book[last()-1]:选取倒数第二个属于bookstore下叫book的元素

-/bookstore/book[position()<3]:选取属于bookstore下叫book的前两个元素

-bookstore/book[@lang]:选取属于bookstore下叫book的,含有属性lang元素

-bookstore/book[@lang="cn"]:选取属于bookstore下叫book的,含有属性lang的值是cn的元素

-/bookstore/book[@price<90]:选取属于bookstore下叫book的,含有属性price的,且值小于90的元素

-/bookstore/book[@price<90]/title:选取属于bookstore下叫book的,含有属性price的,且值小于90的元素的子元素title

(5)通配符

- ‘*’:任何元素节点

- @*:匹配任何属性节点

-node():匹配任何类型的节点

(6)选取多个路径

-//book/title | //book/author:选取book元素中的title和author元素

-//title | //price:选取文档中所有的title和price元素

5、etree

(1)lxml库

-python的HTML/XML的解析器

-官方文档:http://lxml.de/index.html

-功能:

         -解析HTML

'''
安装lxml
'''
from lxml import etree
'''
用lxml来解析HTML代码
'''
text = '''

'''

#利用etree.HTML把字符串解析成HTML文档
html = etree.HTML(text)
s = etree.tostring(html)
print(s)
运行:
b'\n'

--文件读取

from lxml import etree

#只能读取xml格式内容,html报错
html = etree.parse("./v31.html")
rst = etree.tostring(html,pretty_print=True)
print(rst)

-etree和XPath的配合使用

from lxml import etree

#只能读取xml格式内容,html报错
html = etree.parse("./v31.html")
print(type(html))

rst = html.xpath('//book')
print(type(rst))
print(rst)

#xpath的意思是查找带有category属性值为sport的book元素
rst = html.xpath('//book[@category="sport"]')
print(type(rst))
print(rst)

#xpath的意思是查找带有category属性值为sport的book元素下的year元素
rst = html.xpath('//book[@category="sport"]/year')
rst = rst[0]
print(type(rst))
print(rst.tag)
print(rst.text)
运行:


[, , ]

[]

year
2010

6、CSS选择器 BeautifulSoup4

-现在使用BeautifulSoup4

-http://beautifulsoup.readthedocs.io/zh_CN/v4.4.0/

-几个常用提取信息工具的比较

        -正则:很快,不好用,不用安装

        -beautifilsoup:慢,使用简单,安装简单

        -lxml:比较快,使用简单,安装一般

from urllib import request
from bs4 import BeautifulSoup

url = 'http://www.baidu.com'

rsp = request.urlopen(url)
content = rsp.read()

soup = BeautifulSoup(content,'lxml')
#bs自动转码
content = soup.prettify()
print(content)

(1)四大对象

-Tag

-NavigableString 

-BeautifulSoup

-Comment

-Tag

     -对应Html中的标签

     -可以通过soup.tag_name

     -tag两个重要属性:name、attrs

from urllib import request
from bs4 import BeautifulSoup

url = 'http://www.baidu.com'

rsp = request.urlopen(url)
content = rsp.read()

soup = BeautifulSoup(content,'lxml')
#bs自动转码
content = soup.prettify()
#print(soup.head)
print('==' * 12)
print(soup.link)
print(soup.link.name)
print(soup.link.attrs['type'])
#可以修改,因为已经得到并放进了内存中
soup.link.attrs['type'] = 'hahaha'
print(soup.link)
print('==' * 12)
运行:
========================

link
image/x-icon

========================

-NavigableString   对应内容值

-BeautifulSoup

       -表示的是一个文档的内容,大部分可以把他当作tag对象 

       -一般我们可以用soup来表示

from urllib import request
from bs4 import BeautifulSoup

url = 'http://www.baidu.com'

rsp = request.urlopen(url)
content = rsp.read()

soup = BeautifulSoup(content,'lxml')
#bs自动转码
content = soup.prettify()
print('==' * 12)
print(soup.link)
print(soup.link.name)
print(soup.link.attrs['type'])
#可以修改,因为已经得到并放进了内存中
soup.link.attrs['type'] = 'hahaha'
print(soup.link)
print('==' * 12)

#NavigableString
print(soup.title)
print(soup.title.name)
print(soup.title.attrs)
print(soup.title.string)
print("==" * 12)
print(soup.name)
print(soup.attrs)

运行:
========================

link
image/x-icon

========================
百度一下,你就知道
title
{}
百度一下,你就知道
========================
[document]
{}
[document]

-Comment

       -特殊类型的NavigableString类

       -对其输出,则内容不包括注释符号

(2)遍历文档对象

-contents:tag的子节点以列表的方式给出

-children:子节点以迭代器形式返回

-descendants:所子孙节点

-string

from urllib import request
from bs4 import BeautifulSoup

url = 'http://www.baidu.com'

rsp = request.urlopen(url)
content = rsp.read()

soup = BeautifulSoup(content,'lxml')
#bs自动转码
content = soup.prettify()
print('==' * 12)
print(soup.link)
print(soup.link.name)
print(soup.link.attrs['type'])
#可以修改,因为已经得到并放进了内存中
soup.link.attrs['type'] = 'hahaha'
print(soup.link)
print('==' * 12)

#NavigableString
print(soup.title)
print(soup.title.name)
print(soup.title.attrs)
print(soup.title.string)
print("==" * 12)
print(soup.name)
print(soup.attrs)
运行:
========================




百度一下,你就知道
========================

(3)搜索文档对象

-find_all(name,attrs,recursive,text,**kwargs)

      -name:按照那个字符串搜索,可以传入的内容为

             -字符串、正则表达式、列表

             -keyworld参数,可以用来表示属性

             -text:对应tag的文本值

from urllib import request
from bs4 import BeautifulSoup

url = 'http://www.baidu.com'

rsp = request.urlopen(url)
content = rsp.read()

soup = BeautifulSoup(content,'lxml')

#print(soup.name)
print("==" * 12)
#tags = soup.find_all(name="meta")

#正则
import re
tags = soup.find_all(re.compile("^me"),content="always")
for tag in tags:
    print(tag)
print("==" * 12)

运行:
========================

========================

(4)css选择器

-使用soup.select,返回一个列表

-通过标签名称:soup.select("title")

-通过类名:soup.select(".content")

-id查找:soup.select("#name_id")

-组合查找:soup.select("div #input_content")

-属性查找:soup.select("img[class='photo']")

-获取tag内容:tag.get_text

from urllib import request
from bs4 import BeautifulSoup

url = 'http://www.baidu.com'

rsp = request.urlopen(url)
content = rsp.read()

soup = BeautifulSoup(content,'lxml')

print(soup.prettify())

print("==" * 12)
titles = soup.select("title")
print(titles[0])

print("==" * 12)
metas = soup.select("meta[content='always']")
print(metas[0])

print("==" * 12)
运行:



 
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
  
   百度一下,你就知道
  
  
  
  
  
  
  
  
  
  
 
 
  
  
  
======================== 百度一下,你就知道 ======================== ========================

 

你可能感兴趣的:(python爬虫,Python知识)