精华内容
下载资源
问答
  • I try to parse a huge file.... I try to take , but I can'tIt works only without this stringxml2 = '''Tracking ID'''from lxml import etreetree = etree.XML(xml2)nodes = tree.xpath('/Pa...

    I try to parse a huge file. The sample is below. I try to take , but I can't

    It works only without this string

    xml2 = '''<?xml version="1.0" encoding="UTF-8"?>

    Tracking ID

    '''

    from lxml import etree

    tree = etree.XML(xml2)

    nodes = tree.xpath('/PackageLevelLayout/LevelLayouts/LevelLayout[@levelGuid="4a54f032-325e-4988-8621-2cb7b49d8432"]/LevelLayout/LevelLayoutSectionBase/LevelLayoutItemBase/Name')

    print nodes

    解决方案

    Your nested LevelLayout XML document uses a namespace. I'd use:

    tree.xpath('.//LevelLayout[@levelGuid="4a54f032-325e-4988-8621-2cb7b49d8432"]//*[local-name()="Name"]')

    to match the Name element with a shorter XPath expression (ignoring the namespace altogether).

    The alternative is to use a prefix-to-namespace mapping and use those on your tags:

    nsmap = {'acd': 'http://schemas.datacontract.org/2004/07/ArcherTech.Common.Domain'}

    tree.xpath('/PackageLevelLayout/LevelLayouts/LevelLayout[@levelGuid="4a54f032-325e-4988-8621-2cb7b49d8432"]/acd:LevelLayout/acd:LevelLayoutSectionBase/acd:LevelLayoutItemBase/acd:Name',

    namespaces=nsmap)

    展开全文
  • Python - xpath解析XML、HTML 绝对路径:HTML / body / div / a 相对路径: ./a 专业术语 树:整个HTML或XML结构 节点:HTML中的每个标签,XML中标签就是节点 根节点:树的第一个节点,HTML的根节点就是HTML标签 属性:...

    Python - xpath解析XML、HTML

    绝对路径:HTML / body / div / a

    相对路径: ./a

    专业术语

    树:整个HTML或XML结构

    节点:HTML中的每个标签,XML中标签就是节点

    根节点:树的第一个节点,HTML的根节点就是HTML标签

    属性:节点属性(HTML中就是标签属性)

    from lxml import etree
    

    xpath解析xml

    XML数据格式

    json数据与XML数据时两种通用的数据格式,用于不同语言之间进行数据交流

    将一个超市的商品数据进行传输:

    json:
    {
        "name":"永辉超市",
        "address":"肖家河",
        "goods":[
        {"name":"泡面","price":3.5,"count":50}
        {"name":"火腿肠","price":3,"count":200}
        {"name":"矿泉水","price":2,"count":30}
        ]
    }
    
    XML:
    <supermarket>
        <name>永辉超市</name>
    
        <address>肖家河</address>
    
        <goodsList>
            <goods name = "泡面" price = "3.5" count = "50"></goods>
            <goods name = "火腿肠" price = "3" count = "200"></goods>
            <goods name = "矿泉水" price = "2" count = "30"></goods>
        </goodsList>
        <workerList>
          <cashier name = "张三" pay = "4000"></cashier>
          <shoppingGuide name = "李四" pay = "3000"></shoppingGuide>
        </workerList>
    </supermarket>
    
    1. 准备数据
    xml_data ="""
    <supermarket>
        <name>永辉超市</name>
        <address>肖家河</address>
        <goodsList>
            <goods name = "泡面" price = "3.5" count = "50"></goods>
            <goods name = "火腿肠" price = "3" count = "200"></goods>
            <goods name = "矿泉水" price = "2" count = "30"></goods>
        </goodsList>
        <workerList>
            <cashier name = "张三" pay = "4000"></cashier>
            <shoppingGuide name = "李四" pay = "3000"></shoppingGuide>
        </workerList>
    </supermarket>
    """
    
    1. 创建树对象,并且获取数据的根节点
    supermarket = etree.XML(xml_data)
    
    1. 获取标签(获取节点)

      节点对象.xpath(路径)

      a.写绝对路:不管xpath前面的节点对象是什么,路径从根节点开始写

      写法:/绝对路径

    cashier = supermarket.xpath('/supermarket/workerList/cashier')
    

    ​ b.相对路径:用.表示当前节点,xpath前面是谁,当前节点就是谁

    ​ …表示当前节点的上层节点

    ​ 注意:./ 可省略

    cashier = supermarket.xpath('./workerList/cashier')
    print(cashier)   #[<Element cashier at 0x1d4299ba980>]
    
    cashier = supermarket.xpath('../workerList/cashier')
    print(cashier)
    

    ​ c.//路径 — 从任意位置开始全局搜索

    ​ 查找方式和功能和xpath前的节点无关

    result = supermarket.xpath('//cashier')
    print(result)   #[<Element cashier at 0x1d4299ba980>]
    
    goods = supermarket.xpath('//goodsList/goods')
    print(goods)  #[<Element goods at 0x1d4299ba9c0>, <Element goods at 0x1d4299baa00>, <Element goods at 0x1d4299baa40>]
    
    1. 获取节点内容

      语法:获取节点的路径/text()

    name = supermarket.xpath('./name/text()')
    print(name)   #['永辉超市']
    
    1. 获取节点属性值

      语法:获取节点的路径/@属性名

    goods = supermarket.xpath('//goodsList/goods/@name')
    print(goods)   #['泡面', '火腿肠', '矿泉水']
    

    xpath解析HTML

    html = etree.HTML(open('test.html', 'r', encoding='utf-8').read())
    
    h1 = html.xpath('/html/body/h1')
    print(h1)   #[<Element h1 at 0x273af64aa40>]
    
    h1 = html.xpath('//h1')
    print(h1)   #[<Element h1 at 0x273af64aa40>]
    

    加谓语(加条件)

    语法:选中标签的路径[谓语]

    1)、[N] — 获取同层的第N个标签

    
    p = html.xpath('//p[1]/text()')   #所在父标签的第一个p标签的第一个评标前内容
    print(p)  #['肖家河大厦', '泡面', '矿泉水', '面包', '充电宝']
    
    p = html.xpath('./body/p/text()')
    print(p)   #['肖家河大厦']
    
    result = html.xpath('body/ul/li[2]/p/text()')
    print(result)   #['矿泉水', '2', '120']
    

    2)、[last()] — 获取同层的最后一个标签

    [last() - N] — 获取同层的倒数第(N+1)个标签

    counts = html.xpath('body/ul/li/p[last()]/text()')
    print(counts)   #['15', '120', '42', '10']
    
    bread = html.xpath('body/ul/li[last() - 1]/p[last()]/text()')
    print(bread)   #['42']
    

    3)、[position() > N]

    [position() >= N]

    goods = html.xpath('body/ul/li[position() < 3]/p/text()')
    print(goods)   #['泡面', '3.5', '15', '矿泉水', '2', '120']
    

    4)、[@属性名] — 获取有指定属性的标签

    result = html.xpath('body/div/p[@class]/text()')
    print(result)   #['p1', 'p2', 'p4']
    

    [@属性名 = 属性值] — 获取指定属性为指定值的标签

    result = html.xpath('body/div/p[@class = "c1"]/text()')
    print(result)
    

    5)、[标签 >/</>=/<=/= 数据] — 将标签按照指定子标签的内容进行筛选

    prices = html.xpath('body/ul/li[p[2]>2]/p/text()')
    prices = html.xpath('./body/ul/li[p[2]>2]/p/text()')
    print(prices)
    

    6、通配符 *

    获取最后一个div下的所有标签的内容

    result = html.xpath('body/div[last()]/*/text()')
    print(result)   #['p1', 'p2', 'a1', 'span1']
    
    result = html.xpath('body/div[last()]/*[@class]/text()')
    print(result)  #['p1', 'span1']
    
    result = html.xpath('body/div[last()]/*[@*]/text()')
    print(result)  #['p1', 'a1', 'span1']
    
    result = html.xpath('//img/@*')
    print(result)  #['https://image1.guazistatic.com/qn2107010956026670c8553db23db93154432c791292ae.jpg?imageView2/1/w/270/h/180/q/88', '']
    

    7、分支(获取若干个路径)

    result = html.xpath('body/ul/li/p[1]/text()|body/ul/li/p[2]/text()')
    print(result)   #['泡面', '3.5', '矿泉水', '2', '面包', '5', '充电宝', '150']
    
    test.html
    <!DOCTYPE html>
    <html lang="en">
    <head>
        <meta charset="UTF-8">
        <title>Title</title>
    </head>
    <body>
        <h1>永辉超市</h1>
            <p>肖家河大厦</p>
            <ul>
                <li>
                    <p class="name">泡面</p>
                    <p class="price">3.5</p>
                    <p class="count">15</p>
                </li>
                <li>
                    <p class="name">矿泉水</p>
                    <p class="price">2</p>
                    <p class="count">120</p>
                </li>
                <li>
                    <p class="name">面包</p>
                    <p class="price">5</p>
                    <p class="count">42</p>
                </li>
    
                <li>
                    <p class="name">充电宝</p>
                    <p class="price">150</p>
                    <p class="count">10</p>
                </li>
            </ul>
            <div>
            <p class="">p1</p>
            <p class="c1">p2</p>
            <p id="p1">p3</p>
            <p class="c2">p4</p>
            </div>
            <div id="div1">
            <p class="">p1</p>
            <p>p2</p>
            <a href="">a1</a>
            <span class="">span1</span>
            <img src="https://image1.guazistatic.com/qn2107010956026670c8553db23db93154432c791292ae.jpg?imageView2/1/w/270/h/180/q/88" alt="">
            </div>
    </body>
    </html>
    

    xpath解析 豆瓣电影数据

    导包

    from selenium.webdriver import Chrome
    from lxml import etree
    import csv
    import time
    

    获取更多数据(翻页)

    def get_more():
        more = browser.find_element_by_css_selector('.more')
        more.click()
    

    获取网页数据

    def get_message():
        movie_name = []
        movie_score = []
        movie_poster = []
        movie_detail = []
        for movie in movies:
            movie_name.append((movie.xpath('div/img/@alt')))
            movie_score.append(movie.xpath('p/strong/text()'))
            movie_poster.append(movie.xpath('div[@class = "cover-wp"]/img/@src'))
            movie_detail.append(movie.xpath('@href'))
        return zip(movie_name,movie_score,movie_poster,movie_detail)
    

    保存数据

    def writer(m_message):
        file = open('files/douban/movies.csv', 'w', encoding='utf-8')
        writer = csv.writer(file)
        writer.writerow(['电影名称','电影评分','电影海报','电影详情'])
        for movie in m_message:
            writer.writerow(movie)
        file.close()
    

    调用

    browser = Chrome()
    for index in range(0,121,20):
        browser.get(f'https://movie.douban.com/explore#!type=movie&tag=%E7%83%AD%E9%97%A8&sort=recommend&page_limit=20&page_start={index}')
        tree = etree.HTML(browser.page_source)
        movies = tree.xpath('body/div[@id = "wrapper"]/div[@id = "content"]/div[@*]/div[@class = "article"]/div[@class = "gaia"]/div[@class = "list-wp"]/div/a')
        writer(get_message())
        get_more()
        print(index)
        time.sleep(2)
    
    展开全文
  • 1. 背景目前爬虫解析网页的技术有:Json, 正则表达式,BeautifulSoup,PyQuery,XPathXPath 教程 官方文档:...XPath (XML Path Language) 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属...

    1. 背景

    目前爬虫解析网页的技术有:Json, 正则表达式,BeautifulSoup,PyQuery,XPath

    XPath 教程 官方文档:

    http://www.w3school.com.cn/xpath/index.asp

    2. XPath简述

    2.1. 什么是XPath?

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

    2.2. XPath 开发工具

    1.开源的XPath表达式编辑工具: XMLQuire(XML格式文件可用)

    2.Chrome插件 XPath Helper

    3.Firefox插件 XPath Checker

    2.3. XPath语法的解析库 —— lxml库

    lxml 是一个HTML/XML的解析器,主要的功能是解析和提取 HTML/XML 数据,我们可以利用XPath语法,来快速的定位特定元素以及节点信息。

    lxml和正则一样,也是用 C 实现的,是一款高性能的 Python HTML/XML 解析器。

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

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

    3. 什么是XML?

    XML 指可扩展标记语言(EXtensible Markup Language)

    XML 是一种标记语言,很类似 HTML

    XML 的设计宗旨是传输数据,而非显示数据

    XML 的标签需要我们自行定义。

    XML 被设计为具有自我描述性。

    XML 是 W3C 的推荐标准

    XML 官方文档:http://www.w3school.com.cn/xml/index.asp

    3.1. XML 和 HTML 的区别

    数据格式描述设计目标

    XMLExtensible Markup Language (可扩展标记语言)被设计为传输和存储数据,其焦点是数据的内容。

    HTMLHyperText Markup Language (超文本标记语言)显示数据以及如何更好显示数据。

    HTML DOMDocument Object Model for HTML (文档对象模型)通过 HTML DOM,可以访问所有的 HTML 元素,连同它们所包含的文本和属性。可以对其中的内容进行修改和删除,同时也可以创建新的元素。

    3.2. XML文档示例

    可以在 http://www.w3school.com.cn/example/xmle_examples.asp 找到很多XML文档示例。

    <?xml version="1.0" encoding="utf-8"?>

    Everyday Italian

    Giada De Laurentiis

    2005

    30.00

    Harry Potter

    J K. Rowling

    2005

    29.99

    XQuery Kick Start

    James McGovern

    Per Bothner

    Kurt Cagle

    James Linn

    Vaidyanathan Nagarajan

    2003

    49.99

    Learning XML

    Erik T. Ray

    2003

    39.95

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    3.3. HTML DOM 结构

    HTML DOM 定义了访问和操作 HTML 文档的标准方法。DOM 将 HTML 文档表达为树结构。

    3.4. XML的节点关系

    3.4.1. 约定

    3.4.2. 关系

    父(Parent):

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

    上图中book元素 是 title,author(多个),year , price 元素的父辈。

    子(Children):

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

    上图中,title,author,year,price元素都是 book元素的子:

    兄弟(Sibling):

    上图中,title,author,year,price元素都是兄弟。

    祖先(Ancestor):

    某节点的父辈、父辈的父辈,往上递推。

    上图中,title元素的祖先是 book元素。

    后代(Descendant):

    某节点的子,子的子,往后递推。

    上图中,book元素的后代是title元素。

    4. XPath基本语法

    # http://blog.csdn.net/zheng12tian/article/details/40617303

    # XPath 基础表达式:

    /node 表示在xml文档的根目录查找结点名称为node的结点

    ./node 表示在当前结点下查找结点名称为node的结点

    //node 表示在xml文档中递归查找结点名称为node的节点

    //* 表示在xml文档中查询所有的结点,但是排除文本节点

    //node() 表示在xml文档中查询所有结点,包含文本节点

    //text() 表示在xml文档中递归查找所有的文本节点

    //*/text()[contains(., 'test')] 表示在xml文档中递归查找所有结点,条件为该结点的文本节点包含"test"

    //node[@id] 表示在xml文档中递归查找结点名称为node的结点,条件为该结点必须含有id属性

    //node[id] 表示在xml文档中递归查找结点名称为node的结点,条件为该结点必须含有结点名称为id的结点

    //nodes[node/id] 表示递归查找nodes结点,条件为nodes结点下必须有node结点,且node结点下必须有id结点

    //nodes[@id]/node[id] 表示递归查找含有id属性的nodes结点下的node结点,条件为node结点下必须含有id结点

    //nodes[@id]/node[0] 表示递归查找含有id属性的nodes结点下的第一个node结点

    //nodes[@id]/node[last()] 表示递归查找含有id属性的nodes结点下的最后一个node结点

    //nodes/node[position() < 4] 表示递归查找nodes结点下索引小于4的node结点

    //nodes[@id]/node[position() < last()] 递归查找含有id属性的nodes结点下除最后一个结点外的node结点

    /nodes/child::node()[name()='node'] 表示查找nodes结点下结点名称为node的子结点

    /nodes/child::node 等同于/nodes/node表示查找nodes下的node子结点

    /nodes/node/attribute::id 等同于/nodes/node/@id表示查找nodes结点下的node结点的id属性

    //nodes[@id='1001']/node[starts-with(@id, '1')] 表示查找id属性为1001的nodes结点下的id属性以1开头的node结点

    //@*[ends-with(., '1')] 表示查找以1结尾所有属性

    (//* | //@*)[substring(name(), 1, 5) = 'class'] 查找所有结点名称或属性名称的1到5之间的字符等于'class'的结点

    //node[@attr!='-2' and @attr!='2'] 查找所有node节点,其attr属性不等于2和-2

    # XPath 文档轴用途:

    self 选择当前节点

    parent 选择当前节点的父节点

    child 选择当前节点的所有子节点

    attribute 选择当前节点的所有属性

    ancestor 选择当前节点的所有祖先,包括父节点、父节点的父节点等等

    ancestor-or-self 选择当前节点的祖先以及当前节点本身

    descendant 选择当前节点的所有后代,包括子节点、子节点的子节点等等

    descendant-or-self 选择当前节点的后代以及当前节点本身

    preceding 选择整个文档中出现在当前节点前面的所有节点

    preceding-sibling 选择文档中出现在当前节点前面的所有同胞节点(即与当前节点同级的节点)

    following 选择整个文档中出现在当前节点后面的所有节点

    following-sibling 选择文档中出现在当前节点后面的所有同胞节点(即与当前节点同级的节点)

    namespace 选择当前节点的所有名称空间节点

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    5. 一些实际案例

    5.1. 寻找页面通用地址,进行翻页

    def parseResponse(self, response):

    pageUrl = response.xpath('//*[@id="pagn"]//a/@href').extract_first(default = '')

    # 去掉不必要的内容,以便达到更好的去重效果

    followUrl = re.sub(r'&qid=.+&spIA=.+', '', pageUrl, count=1)

    # numberRes = ['1', '2', '3', '95']

    numberRes = response.xpath('string(//*[@id="pagn"])').re(r'\d+') # numberRes 重要,所以要确保正确得到总页数

    for page in range(1, int(numberRes [-1]) + 1):

    yield response.follow(

    # 按照page值构造其他页链接

    url = re.sub(r'page=\d+', f'page={page}', followUrl, count = 1),

    meta = {'dont_redirect': True},

    callback = self.parseNextPage,

    errback = self.error

    )

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    5.2. 结合re使用

    # 获取搜索结果数

    countRes = response.xpath('//*[@id="s-result-count"]/text()').re_first(r'[0-9,]+ of ([0-9,]+)', '0').replace(',', '')

    count = int(countRes)

    # count = 1699

    1

    2

    3

    4

    5.3. 寻找相似性,利用starts-with用法全部提取

    所有商品列表

    # 全部以相同的字符result_开始

    # 解决方法: 用starts-with(@属性名称, 属性相同的部分)

    liRes = response.xpath('//li[starts-with(@id,"result_")]')

    1

    2

    3

    4

    标题

    title = listElem.xpath('.//a[@title]/@title').extract_first()

    1

    评分

    avgStar = listElem.xpath('string(//*[@name=$val])', val = asin).extract_first(default='0')

    1

    评论数

    totalReviews = listElem.xpath('//*[@name=$val]/following-sibling::a/text()', val = asin).extract_first(default='0')

    1

    价格

    price = listElem.xpath('.//span[@aria-label]/@aria-label | .//span[contains(.,"$")]/text()').extract_first(default='0')

    1

    商标:brand,直接通过chrome工具解析出来

    brand = listElem.xpath('string(div/div/div/div[2]/div[last()-1]/div[2])').extract_first(default='')

    1

    搜索结果序号

    resultID = int(listElem.xpath('@id').re_first(r'result_(\d+)'))

    1

    图片链接

    image_url = listElem.xpath('.//img/@src').extract_first()

    1

    卖家总数

    listElem.xpath('.//*[contains(.,"offer")]//text()').extract()

    1

    # 获取搜索列表下,每个商品的唯一标识号,标题

    liRes = response.xpath('//li[starts-with(@id,"result_")]')

    if liRes:

    for listElem in liRes:

    # 商品唯一标识号

    # It returns None if no element was found

    asin = listElem.xpath('@data-asin').extract_first()

    # 标题

    title = listElem.xpath('.//a[@title]/@title').extract_first()

    # 评分

    avgStar = listElem.xpath('string(//*[@name=$val])', val = asin).extract_first(default='0')

    # 评论数

    totalReviews = listElem.xpath('//*[@name=$val]/following-sibling::a/text()', val = asin).extract_first(default='0')

    # 价格, contains(.,"$")中的.代表text

    price = listElem.xpath('.//span[@aria-label]/@aria-label | .//span[contains(.,"$")]/text()').extract_first(default='0')

    # 商标,chrome工具的结果是://*[@id="result_1"]/div/div/div/div[2]/div[1]/div[2]/span[2]

    # 然后进行改造

    brand = listElem.xpath('string(div/div/div/div[2]/div[last()-1]/div[2])').extract_first(default='')

    # 搜索结果序号

    resultID = int(listElem.xpath('@id').re_first(r'result_(\d+)'))

    # 图片链接

    image_url = listElem.xpath('.//img/@src').extract_first()

    # 卖家总数

    sellerNum = 0

    for eachOfferText in listElem.xpath('.//*[contains(.,"offer")]//text()').extract():

    result = re.findall(r'(\d+)\s.*?offer', eachOfferText)

    if result:

    sellerNum = sum(int(num) for num in result)

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    5.4. 利用string(.)获取某个标签下连续的一句话

    # 标签套标签,一句话分散在几个标签中,如何提取成一句完整的话?

    # 解决方法: string(.)

    from lxml import etree

    html = '''

    我左青龙,

    右白虎,

    • 上朱雀,

    下玄武.

    老牛在当中,

    龙头在胸口.

    '''

    selector = etree.HTML(html)

    data = selector.xpath('//div[@id="class3"]')[0]

    allText = data.xpath('string(.)') # 实际上是去除了div中间的其他标签

    print(f"allText = {allText}")

    textRes = allText.replace('\n', '').replace(' ', '')

    print(f"textRes = {textRes}")

    # 输出结果:

    allText =

    我左青龙,

    右白虎,

    上朱雀,

    下玄武.

    老牛在当中,

    龙头在胸口.

    textRes = 我左青龙,右白虎,上朱雀,下玄武.老牛在当中,龙头在胸口.

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    5.5. 价格:文本模糊匹配,并利用上下文关系获取信息

    # --- 价格 price1 : with deal or sale or price

    # 发现价格的数据紧跟在这几个字串后面

    priceInfoRes = response.xpath("//div[@id='price']//text()").extract()

    priceInfoResLst = []

    for priceInfo in priceInfoRes:

    priceInfoStripLower = priceInfo.strip().lower()

    if priceInfoStripLower != '':

    priceInfoResLst.append(priceInfoStripLower)

    priceIdx = 0

    # elemIdx = 0

    for elemIdx in range(0, len(priceInfoResLst)):

    elem = priceInfoResLst[elemIdx].strip().lower()

    if (elem == 'sale:') or (elem == 'with deal:') or (elem == 'price:'):

    priceIdx = elemIdx + 1

    break

    if (priceIdx != 0) and (priceIdx < len(priceInfoResLst)):

    price1 = priceInfoResLst[priceIdx].strip()

    else:

    price1 = ''

    if price1 != '':

    # 处理价格:price = $64.32'

    priceRe = re.search(r'([\d\.]+)', price1)

    priceFloat = float(priceRe.group(1)) if priceRe else 0.0

    detailParseResults['price1'] = priceFloat

    else:

    detailParseResults['price1'] = 0.0

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    5.6. 模糊匹配,以及特征提取

    item = {}

    #--- 解析小品类信息category:

    unicorn = response.xpath('string(//*[contains(.,"Best Sellers Rank")])').extract_first(default='')

    rankResults = re.findall(r'#([0-9,]+)\s+in\s+(.+)[^\.#]\s', unicorn)

    isHasRank = False

    # 解析topRank和 topCategory信息

    topRank = 0

    topCategory = 'unknown'

    if len(rankResults) > 0:

    # 说明是大品类信息

    if rankResults[0][1].find(' > ') == -1:

    topRank = int(rankResults[0][0].replace(',', '').strip())

    categoryLst = rankResults[0][1].split('>')

    topCategory = reCategory = ''

    if len(categoryLst) > 0:

    reCategory = re.search(r"(.*?)\(", categoryLst[-1])

    if not reCategory:

    reCategory = categoryLst[-1]

    else:

    reCategory = reCategory.group(1)

    topCategory = reCategory.strip()

    if isHasRank == True:

    startIndex = 1

    else:

    startIndex = 0

    item['topRank'] = topRank

    item['topCategory'] = topCategory

    smallCategoryIndex = 1

    for i in range(startIndex, len(rankResults)):

    item[f"rank{smallCategoryIndex}"] = int(rankResults[i][0].replace(',', '').strip())

    smallCategoryLst = rankResults[i][1].split('>')

    smallCategory = reSmallCategory = ''

    if len(smallCategoryLst) > 0:

    reSmallCategory = re.search(r"(.*?)\(", smallCategoryLst[-1])

    if not reSmallCategory:

    reSmallCategory = smallCategoryLst[-1]

    else:

    reSmallCategory = reSmallCategory.group(1)

    smallCategory = reSmallCategory.strip()

    item[f"category{smallCategoryIndex}"] = smallCategory

    smallCategoryIndex += 1

    1

    2

    3

    4

    5

    6

    7

    8

    9

    10

    11

    12

    13

    14

    15

    16

    17

    18

    19

    20

    21

    22

    23

    24

    25

    26

    27

    28

    29

    30

    31

    32

    33

    34

    35

    36

    37

    38

    39

    40

    41

    42

    43

    44

    45

    解析结果

    5.7. 筛选属性的组合操作

    # 属性的联合操作

    price = response.xpath('//*[@id="priceblock_ourprice" or @id="priceblock_saleprice"]/text()').extract_first(default = '0')

    title = response.xpath('string(//*[@id="productTitle" or contains(@class,"product-title")])').extract_first()

    1

    2

    3

    ————————————————

    版权声明:本文为CSDN博主「Kosmoo」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。

    原文链接:https://blog.csdn.net/zwq912318834/article/details/78178316

    展开全文
  • 1 import codecs2 from lxml importetree3 f=codecs.open("ceshi.html","r","utf-8")4 content=f.read()5 f.close()6 tree=etree.HTML(content)etree提供了HTML这个解析函数,现在我们可以直接对HTML使用xpath了,...

    1 import codecs2 from lxml importetree3 f=codecs.open("ceshi.html","r","utf-8")4 content=f.read()5 f.close()6 tree=etree.HTML(content)

    etree提供了HTML这个解析函数,现在我们可以直接对HTML使用xpath了,是不是有点小激动,现在就尝试下吧。

    在使用xpath之前我们先来看看作为对照的jQuery和RE。

    在jQuery里要处理这种东西就很简单,特别是假如那个ul节点有id的话(比如是

    • ):

    $("#china").each(function(){...});

    具体到此处是:

    $("#leftmenu").children("h3:contains('text')").next("ul").each(function(){...});

    找到id为leftmenu的节点,在其下找到一个内容包含为”text”的h3节点,再取其接下来的一个ul节点。

    在python里要是用RE来处理就略麻烦一些:

    block_pattern=re.compile(u"

    档案

    (.*?)

    ", re.I |re.S)

    m=block_pattern.findall(content)

    item_pattern=re.compile(u"

    (.*?)", re.I |re.S)

    items=item_pattern.findall(m[0])for i initems:print i

    那么用xpath要怎么做呢?其实跟jQuery是差不多的:

    nodes=tree.xpath("/descendant::ul[@id='china']")

    当然,现在没有id的话也就只能用类似于jQuery的方法了。完整的xpath应该是这样写的(注意,原文件中的TAG有大小写的情况,但是在XPATH里只能用小写):

    nodes=tree.xpath(u"/html/body/form/div[@id='leftmenu']/h3[text()='text']/following-sibling::ul[1]")

    更简单的方法就是像jQuery那样直接根据id定位:

    nodes=tree.xpath(u"//div[@id='leftmenu']/h3[text()='text']/following-sibling::ul[1]")

    这两种方法返回的结果中,nodes[0]就是那个“text”的h3节点后面紧跟的第一个ul节点,这样就可以列出后面所有的ul节点内容了。

    如果ul节点下面还有其他的节点,我们要找到更深节点的内容,如下的循环就是把这些节点的文本内容列出:

    nodes=nodes[0].xpath("li/a")for n innodes:print n.text

    对比三种方法应该可以看出xpath和jQuery对于页面的解析都是基于XML的语义进行,而RE则纯粹是基于plain text。RE对付简单的页面是没有问题,如果页面结构复杂度较高的时候(比如一堆的DIV来回嵌套之类),设计一个恰当的RE pattern可能会远比写一个xpath要复杂。特别是目前主流的基于CSS的页面设计方式,其中大部分关键节点都会有id――对于使用jQuery的页面来说则更是如此,这时xpath相比RE就有了决定性的优势。

    附录:基本XPATH语法介绍,详细请参考XPath的官方文档

    XPATH基本上是用一种类似目录树的方法来描述在XML文档中的路径。比如用“/”来作为上下层级间的分隔。第一个“/”表示文档的根节点(注意,不是指文档最外层的tag节点,而是指文档本身)。比如对于一个HTML文件来说,最外层的节点应该是”/html”。

    同样的,“..”和“.”分别被用来表示父节点和本节点。

    XPATH返回的不一定就是唯一的节点,而是符合条件的所有节点。比如在HTML文档里使用“/html/head/scrpt”就会把head里的所有script节点都取出来。

    为了缩小定位范围,往往还需要增加过滤条件。过滤的方法就是用“[”“]”把过滤条件加上。比如在HTML文档里使用“/html/body/div[@id='main']”,即可取出body里id为main的div节点。

    其中@id表示属性id,类似的还可以使用如@name, @value, @href, @src, @class….

    而 函数text()的意思则是取得节点包含的文本。比如:

    hello

    world

    < /div>中,用”div[text()='hello']“即可取得这个div,而world则是p的text()。

    函数position()的意思是取得节点的位置。比如“li[position()=2]”表示取得第二个li节点,它也可以被省略为“li[2]”。

    不过要注意的是数字定位和过滤 条件的顺序。比如“ul/li[5][@name='hello']”表示取ul下第五项li,并且其name必须是hello,否则返回空。而如果用 “ul/li[@name='hello'][5]”的意思就不同,它表示寻找ul下第五个name为”hello“的li节点。

    此外,“*”可以代替所有的节点名,比如用”/html/body/*/span”可以取出body下第二级的所有span,而不管它上一级是div还是p或是其它什么东东。

    而 “descendant::”前缀可以指代任意多层的中间节点,它也可以被省略成一个“/”。比如在整个HTML文档中查找id为“leftmenu”的 div,可以用“/descendant::div[@id='leftmenu']”,也可以简单地使用“ //div[@id='leftmenu']”。

    至于“following-sibling::”前缀就如其名所说,表示同一层的下一个节点。”following-sibling::*”就是任意下一个节点,而“following-sibling::ul”就是下一个ul节点。

    展开全文
  • 在进行网页抓取的时候,分析定位html节点是获取抓取信息的关键,目前我用的是lxml模块(用来分析XML文档结构的,当然也能分析html结构), 利用其lxml.html的xpath对html进行分析,获取抓取信息。首先,我们需要安装一...
  • 使用xpath解析XMl文档

    千次阅读 2017-02-20 17:28:50
    最近几天接触到爬虫框架scrapy需要对返回的数据进行解析和处理,python提供了很好的XML格式数据的处理模式,在这里使用的是lxml第三方的python库来进行XML文档解析,初步学习了一些xpath的内容,XPath 使用路径...
  • Dom和xpath解析xml文件

    2018-12-10 16:30:26
    Mybatis在初始化过程中处理mybatis-config.xml文件以及映射文件时,采用DOM进行解析,并结合使用XPATH解析XML配置文件。如果对前端熟悉的伙伴,应该了解前端的DOM树,这里也一样,DOM会将整个xml文件加入内存中并...
  • python xpath解析html

    2019-09-13 11:05:41
    什么是 XML 1、XML 指可扩展标记语言(EXtensible Markup Language)。 2、XML 是一种标记语言,很类似 HTML 。 3、XML 的设计宗旨是传输数据,而非显示数据 。 4、XML 的标签需要我们自行定义。 5、XML 被设计为...
  • Python XPath解析器的使用

    千次阅读 2018-03-14 22:31:40
    (一)XPath基础知识 XPath (XML Path Language) 是一门在 XML 文档中查找信息的语言,可用来在 XML 文档中对元素和属性进行遍历。 W3School官方文档:...我们可以 将 HTML文件 转换成 XML文档,然后用 XPath ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 10,392
精华内容 4,156
关键字:

pythonxpath解析xml文件

python 订阅