整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

实战python爬虫(三):XPath解析库

实战python爬虫(三):XPath解析库

上?章中, 我们基本上掌握了抓取整个??的基本技能。 但是呢, ?多数情况下, 我们并不需要整个??的内容, 只是需要那么??部分。怎么办呢? 这就涉及到了数据提取的问题。

本课程中, 提供三种解析?式:

  1. xpath解析
  2. bs4解析
  3. re解析

这三种?式可以混合进?使?, 完全以结果做导向, 只要能拿到你想要的数据。 ?什么?案并不重要。 当你掌握了这些之后。 再考虑性能的问题。

XPath是??在 XML ?档中查找信息的语?, XPath可?来在 XML?档中对元素和属性进?遍历,?我们熟知的HTML恰巧属于XML的?个?集,所以完全可以?xpath去查找html中的内容。

?先, 先了解?个概念:

在上述html中,

1. book, id, name, price....都被称为节点.

2. Id, name, price, author被称为book的?节点

3. book被称为id, name, price, author的?节点

4. id, name, price,author被称为同胞节点

OK~ 有了这些基础知识后, 我们就可以开始了解xpath的基本语法了

在python中想要使?xpath,需要安装lxml模块。

pip install lxml

?法:

1. 将要解析的html内容构造出etree对象.

2. 使?etree对象的xpath()?法配合xpath表达式来完成对数据的提取

from lxml import etree
html="""
<book>
    <id>1</id>
    <name>野花遍地?</name>
    <price>1.23</price>
    <nick>臭?腐</nick>
    <author>
        <nick id="10086">周?强</nick>
        <nick id="10010">周芷若</nick>
        <nick class="joy">周杰伦</nick>
        <nick class="jolin">蔡依林</nick>
        <div>
            <nick>惹了</nick>
        </div>
    </author>
    <partner>
    <nick id="ppc">胖胖陈</nick>
    <nick id="ppbc">胖胖不陈</nick>
    </partner>
</book>
"""
et=etree.XML(html)
# 根据节点进?搜索
# result=et.xpath("/book")
# result=et.xpath("/book/id") # /在开头表示?档最开始, /在中间表示??
# result=et.xpath("/book//nick") # //表示后代
result=et.xpath("/book/*/nick") # *表示通配符
print(result)

xpath如何提取属性信息. 我们上?段真实的HTML来给各位讲解?下:

<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="UTF-8" />
        <title>Title</title>
    </head>
    <body>
        <ul>
            <li><a href="http://www.baidu.com">百度
            </a></li>
            <li><a href="http://www.google.com">?
            歌</a></li>
            <li><a href="http://www.sogou.com">搜狗
            </a></li>
        </ul>
        <ol>
            <li><a href="feiji">?机</a></li>
            <li><a href="dapao">?炮</a></li>
            <li><a href="huoche">??</a></li>
        </ol>
        <div class="job">李嘉诚</div>
        <div class="common">胡辣汤</div>
    </body>
</html>


from lxml import etree
tree=etree.parse("1.html")
result=tree.xpath("/html/body/ul/li/a/@href")
print(result)
result=tree.xpath("/html/body/ul/li")
for li in result:
print(li.xpath("./a/@href")) # 局部解析
result=tree.xpath("//div[@class='job']/text()")
# [@class='xxx']属性选取 text()获取?本
print(result)

实战案例:

一、58二手房标题

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from lxml import etree
import requests
if __name__=="__main__":
    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3884.400 QQBrowser/10.8.4560.400'}
    url="https://bj.58.com/ershoufang/"
    page_text=requests.get(url,headers=headers).text
    tree=etree.HTML(page_text)
    titles=tree.xpath("//h3/text()")
    for title in titles:
        print(title)

?

二:彼岸壁纸下载

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from lxml import etree
import requests
import os
if __name__=="__main__":
    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3884.400 QQBrowser/10.8.4560.400'}
    url="https://pic.netbian.com/4kfengjing/"
    page_text=requests.get(url,headers=headers).text.encode("ISO-8859-1")

    tree=etree.HTML(page_text)
    li_list=tree.xpath('//div[@class="slist"]//li')

    if not os.path.exists("./piclibs"):
        os.mkdir('./piclibs')

    for li in li_list:
        img_src='https://pic.netbian.com/'+li.xpath('./a/img/@src')[0]
        # print()
        img_name=li.xpath('./a/img/@alt')[0]+'.jpg'
        # print(img_name,img_src)
        img_data=requests.get(url=img_src,headers=headers).content
        img_path="piclibs/"+img_name
        with open(img_path,"wb") as fp:
            fp.write(img_data)
            print(img_name,"下载成功")

?

三、全国城市名称爬取

#!/usr/bin/env python
# -*- coding:utf-8 -*-
from lxml import etree
import requests
import os
if __name__=="__main__":
    headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.25 Safari/537.36 Core/1.70.3884.400 QQBrowser/10.8.4560.400'}
    url="https://www.aqistudy.cn/historydata/"
    page_text=requests.get(url,headers=headers).text

    tree=etree.HTML(page_text)
    #全部城市
    all_city_list=tree.xpath('//div[@class="bottom"]//li')
    all_city_names=[]
    for li in all_city_list:
        city_name=li.xpath("./a/text()")[0]
        all_city_names.append(city_name)
        for city in all_city_names:
            print(city)
    # print(all_city_names)

    #热门城市
    # hot_city_names=[]
    # hot_city_list=tree.xpath('//div[@class="hot"]//li')
    # for li in hot_city_list:
    #     city_name=li.xpath("./a/text()")[0]
    #
    #     hot_city_names.append(city_name)
    # print(hot_city_names)

?

关注我:带你从零开始学爬虫。

语言是一种古老且广泛使用的编程语言,它拥有众多第三方库,为开发者提供了各种功能,从数据处理到网络通信,再到图形界面等。以下是一些流行的C语言第三方库的详细介绍:

  1. GLib - GLib是一个跨平台的、用C语言编写的实用工具库。它提供了一系列的数据结构、算法、内存管理、文件操作等基础功能。GLib是GTK+图形用户界面工具包的基础,广泛应用于Linux和其他类Unix系统的软件开发中。GLib提供的主要功能包括:事件循环、动态数组、哈希表、字符串处理、时间操作、内存分配等。
  2. GNU Scientific Library (GSL) - GSL是一个用于数值计算的C语言库,提供了广泛的数学函数,如线性代数、特殊函数、随机数生成等。GSL适用于科学和工程计算,其API设计注重数值稳定性和准确性。GSL提供的主要功能包括:线性代数(向量、矩阵运算)、数值积分、随机数生成、统计运算、特殊函数(如伽玛函数、贝塞尔函数)等。
  3. OpenSSL - OpenSSL是一个强大的加密库,它为应用程序提供了一系列的加密和SSL/TLS功能。OpenSSL广泛应用于网络通信的安全,支持多种加密算法、密钥交换协议和摘要算法。它还提供了命令行工具,用于生成密钥、创建证书请求和证书等。OpenSSL的主要组件包括:加密库(libcrypto)、SSL/TLS库(libssl)、命令行工具(如openssl)等。
  4. SQLite - SQLite是一个轻量级的、嵌入式的数据库引擎,它是一个C语言库,提供了不需要服务器的、零配置的数据库管理系统。SQLite支持标准的SQL语法,适用于移动应用、网站、桌面应用等场景。SQLite的主要特点包括:轻量级、单文件数据库、无需独立的服务器进程、支持事务、支持多种数据类型等。
  5. PCRE (Perl Compatible Regular Expressions) - PCRE是一个C语言编写的正则表达式库,它与Perl的正则表达式非常相似。PCRE被许多应用和编程语言用作正则表达式的处理引擎,支持多种字符编码和正则表达式语法。PCRE的主要功能包括:正则表达式匹配、替换、分割等。
  6. FFmpeg - FFmpeg是一套可以用来记录、转换数字音视频,并进行流媒体播放的完整的解决方案。它提供了多个库,包括libavcodec、libavformat、libavutil等,用于处理多媒体数据。FFmpeg支持多种音视频格式,可以用于开发媒体播放器、视频编辑器等应用。FFmpeg的主要功能包括:编解码(音视频编解码、图像编解码)、容器格式处理(如MP4、AVI、MKV等)、流媒体协议处理(如RTMP、HLS等)。
  7. cJSON - cJSON是一个轻量级的JSON解析库,它用C语言编写,易于使用和理解。cJSON适用于需要JSON数据交换的嵌入式系统,可以解析和生成JSON数据结构。cJSON的主要功能包括:JSON解析、JSON生成、JSON遍历等。
  8. libxml2 - libxml2是一个用于解析和构建XML和HTML文档的C语言库,它提供了API用于处理XML数据,包括SAX、DOM和XPath等功能。libxml2广泛应用于Web开发、文档处理等领域。libxml2的主要功能包括:XML解析、XML生成、XPath查询、XSLT转换等。
  9. zlib - zlib是一个广泛使用的压缩和解压缩库,它提供了一种用于数据压缩的DEFLATE算法的实现。zlib常用于网络传输和文件压缩,如HTTP协议中的deflate编码、gzip文件格式等。zlib的主要功能包括:压缩数据、解压缩数据、流处理等。
  10. libpng - libpng是一个读写PNG图像文件的C语言库,它是PNG文件格式官方参考库。与zlib一起使用,可以实现PNG图像的压缩和解压缩。libpng广泛应用于图像处理、Web开发和游戏开发等领域。libpng的主要功能包括:PNG图像读取、PNG图像写入、PNG图像处理等。
  11. FreeType - FreeType是一个用于渲染字体的高级库,它支持多种字体格式,如TrueType、Type 1等。FreeType提供了API用于字体管理和文本渲染,广泛应用于图形界面、游戏开发、PDF文档处理等领域。FreeType的主要功能包括:字体加载、字形渲染、字形变换等。
  12. SDL (Simple DirectMedia Layer) - SDL是一个跨平台的C语言库,用于开发游戏和多媒体应用程序。它提供了低层次的访问音频、键盘、鼠标、操纵杆和图形硬件的接口。SDL广泛应用于游戏开发、模拟器、多媒体工具等领域。SDL的主要功能包括:音频播放、键盘输入、鼠标输入、图形渲染等。

这些库只是C语言生态中的一部分,每个库都有其特定的用途和优势,为C语言开发者提供了强大的工具来创建高效、可靠的应用程序。这些库的源代码通常都是开放的,可以自由地使用、修改和分发,为C语言开发者提供了丰富的资源。

除了上述的库,还有许多其他的C语言第三方库,如用于网络编程的libcurl、用于图像处理的OpenCV、用于数学计算的GNU MP等。这些库各自都有其特点和用途,可以根据具体的应用场景选择合适的库。

在C语言编程中,选择合适的第三方库可以帮助开发者提高开发效率,减少重复造轮子的工作,同时也可以提高应用程序的性能和可靠性。使用第三方库还可以使应用程序更加模块化,便于维护和升级。

然而,使用第三方库也需要考虑到一些问题,如库的兼容性、稳定性、安全性等。因此,在选择第三方库时,应该尽量选择成熟、活跃、社区支持良好的库,并对其进行充分的测试和验证。

总之,C语言拥有丰富的第三方库资源,这些库为C语言开发者提供了强大的支持和便利。掌握这些库的使用方法和技巧,可以帮助开发者更好地应对各种编程挑战,提高开发效率和应用程序质量。

xml是基于 libxml2解析库的Python封装。libxml2是使用C语言编写的,解析速度很好,不过安装起来稍微有点复杂。安装说明可以参考(http: //Lxml.de/installation.html),在CentOS7上中文安装说明(http://www.cjavapy.com/article/64/),使用lxml库来解析网络爬虫抓取到的HTML是一种非常高效的方式。lxml的html模块特别适合处理HTML内容,它可以快速解析大型HTML文件,并提供XPath和CSS选择器来查询和提取数据。

参考文档:https://www.cjavapy.com/article/65/

一、可能不合法的html标签解析

从网络上抓取到的html的内容,有可能都是标准写法,标签什么的都闭合,属性也是标准写法,但是有可能有的网站的程序员不专业,这样抓到的html解析就有可能有问题,因此,解析时先将有可能不合法的html解析为统一的格式。避免为后续的解析造成困扰。

1、lxml.html

lxml.html是专门用于解析和处理HTML文档的模块。它基于lxml.etree,但是为HTML文档的特点做了优化。lxml.html能够处理不良形式的HTML代码,这对于解析和爬取网页尤其有用。

>>> import lxml.html
>>> broken_html='<ul class="body"><li>header<li>item</ul>'
>>> tree=lxml.html.fromstring(broken_html) #解析html
>>> fixed_html=lxml.html.tostring(tree,pretty_print=True)
>>> print fixed_html
<ul class="body">
<li>header</li>
<li>item</li>
</ul>

2、lxml.etree

lxml.etree是lxml库中用于处理XML文档的模块。它基于非常快的XML解析库libxml2,提供了一个类似于标准库xml.etree.ElementTreeAPI的接口,但是在性能和功能性方面要更加强大。lxml.etree支持XPath、XSLT、和Schema验证等高级XML特性。

>>> import lxml.etree
>>> broken_html='<ul class="body"><li>header<li>item</ul>'
>>> tree=lxml.etree.fromstring(broken_html) #解析html
>>> fixed_html=lxml.etree.tostring(tree,pretty_print=True)
>>> print fixed_html
<ul class="body">
<li>header</li>
<li>item</li>
</ul>

通过以上可以看出,lxml可以正确解析两侧缺失的括号,并闭合标签,但不会额外增加<html>和<body>标签。

二、处理lxml解析出来的html内容

若在html中找到我们想要的内容,用lxml有几种不同的方法,XPath选择器类似Beautiful Soup的find()方法。CSS选择器用法和jQuery中的选择器类似。两种选择器都可以用来查找文档中的元素,但它们各有特点和适用场景。XPath是一种在XML文档中查找信息的语言。它可以用来遍历XML文档的元素和属性。CSS选择器通常用于选择和操作HTML文档中的元素。

1、XPath选择器(/单斜杠表示绝对查找,//双斜杠表示相对查找)

from lxml import etree
source_html="""
         <div>
            <ul>
                 <li class="item-0"><a href="link1.html">first item</a></li>
                 <li class="item-1"><a href="link2.html">second item</a></li>
                 <li class="item-inactive"><a href="link3.html">third item</a></li>
                 <li class="item-1"><a href="link4.html">fourth item</a></li>
                 <li class="item-0"><a href="link5.html">fifth item</a>
             </ul>
         </div>
        """
html=etree.HTML(source_html)
print(html)
result=etree.tostring(html)#会对的html标签进行补全
print(result.decode("utf-8"))

输出结果:

<Element html at 0x39e58f0>
<html><body><div>
<ul>
<li class="item-0"><a href="link1.html">first item</a></li>
<li class="item-1"><a href="link2.html">second item</a></li>
<li class="item-inactive"><a href="link3.html">third item</a></li>
<li class="item-1"><a href="link4.html">fourth item</a></li>
<li class="item-0"><a href="link5.html">fifth item</a>
</li></ul>
</div>
</body></html>

1)获取某个标签的内容(a标签后不需要加斜杠,否则会报错)

#第一种写法

html=etree.HTML(source_html)
html_data=html.xpath('/html/body/div/ul/li/a')#绝对查找
#html_data=html.xpath('//li/a')#相对查找
print(html)
for i in html_data:
    print(i.text)

输出结果:

<Element html at 0x14fe6b8>
first item
second item
third item
fourth item
fifth item

#第二种写法
#在要找的标签后面加/text(),就是获取标签中的文本内容,结果中直接就是文本内容了,不用在通过text属性获取了。

html=etree.HTML(source_html)
html_data=html.xpath('/html/body/div/ul/li/a/text()')#绝对查找
#html_data=html.xpath('//li/a/text()')#相对查找
print(html)
for i in html_data:
    print(i)

输出结果:

<Element html at 0x128e3b7>
first item
second item
third item
fourth item
fifth item

2)获取a标签下的属性

html=etree.HTML(source_html)
html_data=html.xpath('//li/a/@href') #相对查找
#html_data=html.xpath('/html/body/div/ul/li/a/@href') #绝对查找
for i in html_data:
    print(i)

输出结果:

link1.html
link2.html
link3.html
link4.html
link5.html

3)查找a标签属性等于link2.html的内容

html=etree.HTML(source_html)
html_data=html.xpath('/html/body/div/ul/li/a[@href="link2.html"]/text()')绝对查找
#html_data=html.xpath('//li/a[@href="link2.html"]/text()')#相对查找
print(html_data)
for i in html_data:
    print(i)

输出结果:

['second item']
second item

4)查找最后一个li标签里的a标签的href属性

html=etree.HTML(source_html)
html_data=html.xpath('//li[last()]/a/text()')
print(html_data)
for i in html_data:
    print(i)

输出结果:

['fifth item']
fifth item

5)查找倒数第二个li标签里a标签的href属性

html=etree.HTML(source_html)
html_data=html.xpath('//li[last()-1]/a/text()')
print(html_data)
for i in html_data:
    print(i)

输出结果:

['fourth item']
fourth item

6)查找某个标签id属性值等于value的标签

//*[@id="value"]

7)使用chrome浏览器提取某个标签的XPath

2、CSS选择器(基本上和jQuery选择器用法一样)

选择器

描述

*

选择所有标签

a

选择<a>标签

.link

选择所有class='link'的元素

a.link

选择class='link'的<a>标签

a#home

选择id='home'的<a>标签

a > span

选择父元素为<a>标签的所有<span>子标签

a span

选择<a>标签内部的所有<span>标签

使用示例:

>>> html="""<div>
<tr id="places_area_row" class="body">
<td>header</td>
<td class="w2p_fw">item1</td>
<td class="w2p_fw">item2</td>
<td class="w2p_fw">item3</td>
<td><tr><td class="w2p_fw">header</td>
<td class="w2p_fw">item4</td>
<td class="w2p_fw">item5</td>
<td class="w2p_fw">item6</td></tr></td>
</tr>
</div>"""
>>> tree=lxml.html.fromstring(html)
>>> td=tree.cssselect('tr#places_area_row > td.w2p_fw')[0]
>>> htmlText=td.text_content()
>>> print htmlText
item1

参考文档:https://www.cjavapy.com/article/65/

?