python3爬虫系列11之xpath和css selector方式的内容提取介绍

python3爬虫系列11之xpath和css selector方式的内容提取介绍

前面一个python3爬虫系列10之使用pymysql+pyecharts读取Mysql数据可视化分析,搞得太快了,很多地方学习得不够细节。
回顾一下爬虫过程,其中,(解析网页不是难度,难度在提取内容。)

想要爬取的信息在哪里?它叫什么名字,如何去定位它?

1.前言

接上上科普篇:

python3爬虫系列04之网页解析器:re正则式,BeautifulSoup库的解释

这一篇里面讲了,网页解析器的,re正则式和对BeautifulSoup库以及的他一些解析器做了说明,

但是,后面本人发现,属于长文啰嗦篇啊,估计没多人看,直接总结一下,爬虫的时候,怎么用它,一些常用方式吧。

善于使用BeautifulSoup前,不得不扯一下其他的了。

在这里插入图片描述
我们在用BeautifulSoup解析了网页以后,我们是不是要开始提取需要的内容了,这个时候,就有很多种方式来选择。

2.定位元素常用的两种路径

在目标网页中,找到相应的元素,右键检查元素( F12 ),看到元素的代码信息,找到自己需要的,进行右击,这时候有两种方式可以获得标签的位置的具体描述方式:

  1. 使用 copy selector
  2. 使用 copy XPath

图示:
在这里插入图片描述

这两种复制的路径有什么区别(以tr为例)?

copy XPath复制出来的路径:

/html/body/section/section/section/article/table[1]/tbody/tr[1]

copy selector复制出来的:

body > section > section > section > article >
table.table.table-striped.table-top20 > tbody > tr:nth-child(1)

这两种不同的路径描述方式,使用copy selector复制出来的路径叫做 CSS Selector,使用copy XPath复制出来的叫做XPath。

总之:

  • XPath的路径是按照:谁,在哪,第几个的选择方式
  • CSS Selector是按照:谁,在哪,第几个,长啥样来选择

那么分开来看看具体的使用。

3.内容提取方式一Xpath语言

XPath (XML Path Language) 是一门在 XML 文档中查找信息的语言(并不是解析器!是一种语言格式),可用来在 XML 文档中对元素和属性进行遍历。

一般xpath要配合lxml解析器来使用。

XPath 使用路径表达式来选取 XML 文档中的节点或者节点集。

*表示通配符。匹配任意节点

@*匹配节点中的任何属性

使用“ | ”运算符,选取若干个路径。

注意:

/ 和 // 的区别: / 代表只获取直接子节点; //获取子孙节点。
一般// 用的比较多。

./表示当前节点下,//表示全网页。

XPath语法——选取节点:
在这里插入图片描述
路径表达式类似这种:

/html/body/div[4]/div[2]/div/div[2]/div[14]/a

或者

/html/body/div[@class=”content”] ,

其中第一个路径叫绝对路径,其中每个‘/’就是一个节点。
第二个路径中的[@class=”content”] 是为了在多个相同标签中定位到一个标签。
在这里插入图片描述

在浏览器里面怎么找到你要的内容对应的xpath路径呢?

使用方法:

f12审查元素进去,然后直接在你需要爬的网页上面,找到你想要提取的对应地点,然后点击copy,copy xpath。
在这里插入图片描述
复制出来的xpath语言是这样的:

//*[@id="app"]/div/div/div/dl/dd[1]/div/div/div[1]/p[2]

那么怎么知道复制出来的xpath正不正确呢?

推荐两个xpath的插件。可以不用,也可以用,是用来校验你的xpath的。

在Chrome或Firefox浏览器中,有这样两个关于xpath的插件。可以快速找到对应网页的xpath路径。

  1. Chrome插件 XPath Helper
  2. Firefox插件 XPath Checker

插件使用效果:在这里插入图片描述

当然你也可以直接在这个地方输入,ctrl+F,然后输入:

在这里插入图片描述

关于xpath的其他方法和语法不交了,反正都是copy直接拿来用的我。

最后要注意的就是:使用.xpath() 的时候,其返回值是一个列表list,取值时需要注意。

使用例子在后面:lxnl+xpath。


4.内容提取方式—Css Selector

在用BeautifulSoup解析了网页以后,我们是不是要开始提取需要的内容了,这个时候,我常用:Css Selector的方式。

BeautifulSoup本身不支持XPath表达式,所以可以用Css Selector的方式。

记得在说BeautifulSoup库的介绍时候,我们有说到,bs里面有三种方法来查找元素。

  1. findall() 查找所有节点
  2. find() 查找单个
  3. selsect() 根据css的选择器Selector来查找

现在推荐的,就是第三种方式,根据css的选择器Selector来查找。

为啥?可以复制啊,快啊。

在浏览器里面怎么找到你要的内容对应的Selector路径呢?

使用方法:

f12审查元素进去,然后直接在你需要爬的网页上面,找到你想要提取的对应地点,然后点击copy,Copy Selector。
在这里插入图片描述
复制出来的 CSS Selector路径是这样的:

#app > div > div.tags-panel > ul > li:nth-child(1) > ul > li:nth-child(2)

同样也可以在浏览器里面验证你的CSS Selector路径是否正确?

ctrl+F 然后搜索自动匹配一下,找对了就会高亮。
在这里插入图片描述

4.1 BeautifulSoup结合Css Selector的爬虫提取例子:

#!/usr/bin/python3

import requests
from bs4 import BeautifulSoup

url = 'https://maoyan.com/films'
headers = {
    'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.100 Safari/537.36'
}
response = requests.get(url, headers=headers)
if response.status_code == 200:
    soup = BeautifulSoup(response.text, 'html.parser') #也可用lxml

    # 获取文本,由于select()方法获得是list类型,必须要先获取到确定的元素,才能确定文本内容
    a1 = soup.select('body > div.header > div > div.city-container > div.city-selected')[0].get_text()
    print('Selector方式获取文本内容:',a1)
    a2 = soup.select('.city-name')[0].get_text()  # 按照标签名,id名,类名查找
    print('按标签名,id名,类名查询:',a2)
    a3 = soup.select('div .js-geo-city')  # 组合查找名为jsxxx的div。用空格分开
    print('组合查找:',a3)
    
# 查img的src,a标签中的href属性
    a4 = soup.select('div.movie-item > a > div > img:nth-of-type(2)')[0]['data-src']
    print('找img的src属性:',a4)
    # 重复li取其中一项:
    a5 = soup.select('div.channel-detail.channel-detail-orange')[0].get_text()
    print('重复li取其中一项:',a5)

    # 批量查询,比如table中多组td,div中多组li
    a6 = soup.select('body > div.header > div > div.nav > ul > li')
    for li in a6:
        # print(li)
        a = li.find('a')['href']
        # print(a)
        wz = li.text
        print('批量查找:',wz)
    # 与find方法对比-多但是copy快。
    a3111 = soup.find('div', class_='city-name').text
    print('与find方法对比:',a3111)
else:
    print('error', response.status_code)

图示:

在这里插入图片描述

常用的就是如下的了:

  1. 获取某个节点的文字:比如p标签外面的文字,标题
  2. 获取某个节点的属性值:比如a标签的href,img的src。
  3. 获取某个指定名称的点的文本内容或者属性:比如某个class='city-name’的div的内容。
  4. 批量获取列表型内容,比如table的多个td,div的多个li。

写在了文中。

5.网页解析器lxml库

除了BeautifulSoup解析器以外,还有 lxml 也是python的一个解析库,而且解析效率非常高,支持HTML或XML的解析,支持使用Xpath1.0语法来解析代码。

主要的功能是如何解析和提取 HTML/XML 的数据。

注意:lxml和上面说的两种,xpath和css selector不是同一个类别。这是和BeautifulSoup一个级别的解析器。

使用 pip 安装:pip install lxml

代码使用的时候,主要是lxml的etree库来解析:

from lxml import etree  

利用lxml来 解析HTML代码,在解析HTML代码的时候,如果HTML代码不规范,他会自动的进行补全。

比如:

# 先安装lxml: pip install lxml

from lxml import etree  # 用lxml来解析HTML代码-自动补全
text='''
<div>
    <ul>
         <li class="item-0"><a href="link1.html">first item</a></li>....
'''
# 利用 etree.HTML 把字符串解析成 HTML 文件
html = etree.HTML(text)
# 按字符串序列化HTML文档
result = etree.tostring(html).decode()
print(result )

运行结果:

输出后,会补全了li标签,还添加了body,html标签。
在这里插入图片描述

因为lxml支持xpath,而且lxml快,xpath获得也非常方便,所以,我们

一般采用 “lxml+xpath” 的方式 来快速的定位特定元素以及节点信息。

( lxml+Selector也可以,但是推荐用xpath)

5.1 lxml 结合 xpath的常用方式:

使用xpath语法。应该使用Element.xpath方法。来执行xpath的选择。

示例代码如下:

 trs = html.xpath("//tr[position()>1]")

xpath函数 返回来的永远是一个列表。

获取某个标签的属性:

href = html.xpath("//a/@href") # 获取a标签的href值

获取文本,是通过xpath中的text()函数。

示例代码如下:

address = tr.xpath("./td[4]/text()")[0]

在某个标签下,再执行xpath函数,获取这个标签下的子孙元素,那么应该在斜杠之前加一个点,代表是在当前元素下获取。

示例代码如下:

  address = tr.xpath("./td[4]/text()")[0]

xpath解析器下元素下标从1开始。

5.2 根据读取的对象不同—方式也不同:

1.修正HTML代码,补齐标签

from lxml import etree
html=etree.HTML(text) #Lxml库解析数据,为Element对象
result=etree.tostring(html) #此时可以自动修正HTML代码,补齐标签等等

2.读取本地的HTML文件
读取本地的HTML文件使用parse()方法

from lxml import etree
html=etree.parse(r"文件路径")
result=etree.tostring(html,pretty_print=True)

3.解析在线请求回来的HTML源码
使用requests获取HTML源码后,

html=etree.HTML(res.text)
result = etree.tostring(html).decode() #实现对其的解析

再次提醒:使用.xpath() 的时候,其返回值是一个列表list

5.3 lxml和xpath 爬虫的提取例子:


# xpath函数返回的是一个列表
str ="""
    <div class="wrapper">
        <i class="iconfont icon-back" id="back">马麻花</i>
        <a href="/" id="channel">新浪社会</a>
        <ul id="nav">
            <li><a href="http://domestic.firefox.sina.com/" title="国内">国内</a></li>
            <li><a href="http://world.firefox.sina.com/" title="国际">国际</a></li>
            <li><a href="http://mil.firefox.sina.com/" title="军事">军事</a></li>
            <li><a href="http://photo.firefox.sina.com/" title="图片">图片</a></li>
            <li><a href="http://society.firefox.sina.com/" title="社会">社会</a></li>
            <li><a href="http://ent.firefox.sina.com/" title="娱乐">娱乐</a></li>
            <li><a href="http://tech.firefox.sina.com/" title="科技">科技</a></li>
            <li><a href="http://sports.firefox.sina.com/" title="体育">体育</a></li>
            <li><a href="http://finance.firefox.sina.com/" title="财经">财经</a></li>
            <li><a href="http://auto.firefox.sina.com/" title="汽车">汽车</a></li>
        </ul>
        <i class="iconfont icon-liebiao" id="menu">张三丰</i>
    </div>
    """

from lxml import etree

html=etree.HTML(str)        #创建一个html对象
result1=html.xpath("//a/text()")    #获取所有a标签下的所有内容
print(result1)
result2=html.xpath("//a/@href")    #获取所有a标签下的所有内容
print(result2)
result3=html.xpath("//li/a/text()") #获取标签下的内容
print(result3)
result4=html.xpath('//a[@id="channel"]/text()') #获取带属性的标签的内容
print(result4)
result5=html.xpath("//li[position()<4]/a/text()") #选前三项
print(result5)
result6=html.xpath("//li[1]/a/text()")      #第一个
print(result6)
result7=html.xpath("//li[last()]/a/text()")      #最后一个last()-1倒数第二项
print(result7)
result8=html.xpath("//i[contains(@class,'iconfont')]/text()")   #class类中包含iconfont的取出来
print(result8)

效果:

在这里插入图片描述

补充几种常见情况:

遇到相同的字符开头的多个标签?

<li class="tag-1">需要的内容1</li>
<li class="tag-2">需要的内容2</li>
<li class="tag-3">需要的内容3</li>

想同时爬取时,不需要构造多个Xpath路径,通过 starts-with()便可以获取多个标签内容。

starts-with()如下:

contents = selector.xpath('//li[starts-with(@class,"tag")]/text() ')

当遇到标签套标签情况时,想同时获取文本内容:

<div class="red">需要的内容1
<h1>需要的内容2</h1>
</div>>

可以使用string(.)方法如下:

from lxml import etree

html2 = '''
<div class="red">需要的内容1
<h1>需要的内容2</h1>
</div>>
'''

selector = etree.HTML(html2)
content1 = selector.xpath('//div[@class="red"]')[0]
content2 = content1.xpath('string(.)')
print(content2)

string(.)方法可用于标签套标签情况。

总结:

  1. xpath 和 css selector 是同一类,都是用来定位元素的两种不同的路径。其中xpath比css selector更高效一些。BeautifulSoup和Lxml是同一类,都是解析网页的解析器。

  2. 对于网页解析器BeautifulSoup,它本身不支持XPath表达式,所以可以用Css Selector的方式。

  3. 对于网页解析器Lxml,它支持xpath表达式,也支持Css Selector的方式,推荐使用xpath的方式。


下一篇文章:
python3爬虫系列12之lxml+xpath和BeautifulSoup+css selector不同方式tiobe网站爬取


最后说两句:

lxml只支持xpath1.0,不支持xpath2.0,Xpath2.0支持正则匹配,而1.0不支持,但是目前很多功能用不到。(但是,我还真没找到关于XPATH 2.0的教程或项目实例。截止2019/11月。现在市面上的网页基本上都还是xpath1的。)

其他参考网站:
https://www.cnblogs.com/jjb1997/p/11234638.html
https://www.jianshu.com/p/1660003f40c8
https://www.cnblogs.com/yiyea/p/11446981.html
https://www.cnblogs.com/wsg-python/articles/10182177.html
https://www.cnblogs.com/liudi2017/articles/9158390.html
https://www.cnblogs.com/zhangxinqi/p/9210211.html#_label16

Python爬虫中的selector用于解析提取网页中的特定数据。可以使用Scrapy框架提供的Selector类来构造使用selector选择器。使用selector选择器的步骤如下: 1. 导入必要的模块类,如: ```python from scrapy import Selector ``` 2. 构造一个selector对象,将要解析的网页作为参数传入,如: ```python selector = Selector(text=html) ``` 这里的html是要解析的网页内容3. 使用selector对象来选取提取数据,可以使用xpathcss选择器语法来指定需要的数据。例如,使用xpath选择器可以使用以下语法: ```python data = selector.xpath(&#39;//tag/text()&#39;).extract() ``` 这里的//tag/text()是一个xpath表达式,用来选择tag标签的文本内容4. 对于复杂的选择器,可以使用多个xpathcss选择器进行组合,以便更精确地选取提取数据。 综上所述,使用python爬虫selector可以通过构造selector对象并使用xpathcss选择器语法来选取提取网页中的特定数据。<span class="em">1</span><span class="em">2</span> #### 引用[.reference_title] - *1* [Python爬虫之Scrapy框架系列(10)——Scrapy选择器selector](https://blog.youkuaiyun.com/qq_44907926/article/details/128815032)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] - *2* [Python爬虫之Spider类用法简单介绍](https://download.youkuaiyun.com/download/weixin_38679449/13710337)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

江湖一点雨

原创不易,鼓励鼓励~~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值