python爬虫常用模块-xpath以及lxml

一、模块介绍以及安装

xpath是一个html元素选择器,这个模块是存在lxml库中,安装lxml库后就可以直接使用xpath

pip install lxml 

二、Xpath术语

节点

在 XPath 中,有七种类型的节点:元素、属性、文本、命名空间、处理指令、注释以及文档(根)节点。XML 文档是被作为节点树来对待的。树的根被称为文档节点或者根节点

<?xml version="1.0" encoding="ISO-8859-1"?>

<bookstore> 

<book>
  <title lang="en">Harry Potter</title>
  <author>J K. Rowling</author> 
  <year>2005</year>
  <price>29.99</price>
</book>

</bookstore>

用以上的文档来说明其中的节点

<bookstore> (文档节点)
<author>J K. Rowling</author> (元素节点)
lang="en" (属性节点)

基本值

J K. Rowling就是基本值,其无法再被拆分

节点之间的关系

<book>
  <title>Harry Potter</title>
  <author>J K. Rowling</author>
  <year>2005</year>
  <price>29.99</price>
</book>
  • 父:每个元素以及属性都有一个父
    这个文档中book是title,author,year,price的父元素
  • 子:元素节点可有零个、一个或多个子
    上述例子中title等就是book的子元素
  • 同胞:拥有相同的父的节点
    title、author、year 以及 price 元素都是同胞
  • 先辈:某节点的父、父的父,等等
  • 后辈

三、Xpath语法

选取节点

表达式描述
nodename选取此节点的所有子节点
bookstore选取 bookstore 元素的所有子节点
/从根节点选取
/bookstore选取根元素 bookstore
bookstore/book选取属于 bookstore 的子元素的所有 book 元素
//从匹配选择的当前节点选择文档中的节点,而不考虑它们的位置
//book选取所有 book 子元素,而不管它们在文档中的位置
bookstore//book选择属于 bookstore 元素的后代的所有 book 元素,而不管它们位于 bookstore 之下的什么位置
//@lang选取名为 lang 的所有属性

谓语

谓语用来查找某个特定的节点或者包含某个指定的值的节点。

谓语被嵌在方括号中

表达式描述
/bookstore/book[1]选取属于 bookstore 子元素的第一个 book 元素
/bookstore/book[last()]选取属于 bookstore 子元素的最后一个 book 元素
/bookstore/book[last()-1]选取属于 bookstore 子元素的倒数第二个 book 元素
/bookstore/book[position()< 3]选取最前面的两个属于 bookstore 元素的子元素的 book 元素
//title[@lang]选取所有拥有名为 lang 的属性的 title 元素
//title[@lang=‘eng’]选取所有 title 元素,且这些元素拥有值为 eng 的 lang 属性
/bookstore/book[price>35.00]选取 bookstore 元素的所有 book 元素,且其中的 price 元素的值须大于 35.00
/bookstore/book[price>35.00]/title选取 bookstore 元素中的 book 元素的所有 title 元素,且其中的 price 元素的值须大于 35.00

选取未知节点

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

表达式描述
*匹配任何元素节点
@*匹配任何属性节点
node()匹配任何类型的节点

四、lxml

因为xpath模块在python3中包含于lxml中,那么我们也简要的来描述一下lxml模块

  • 1、导入etree库
from lxml import tree
  • 2、利用etree.HTML,将字符串转换为Element对象具有xpath的方法,返回结果的列表,能够接受byte类型的数据str类型的数据
html = etree.HTML(text)
ret_list = html.xpath("xpath字符串")

五、实例

import requests
import lxml.html
import csv

class DouBan():
    def __init__(self):
        self.url_temp = "https://movie.douban.com/top250?start={}&filter="
        self.headers = {'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/81.0.4044.122 Safari/537.36'}

    # 获取top250的所有html页面信息
    def get_page_url(self):
        url_list = [ self.url_temp.format( i*25 ) for i in range(10)]
        return url_list

    # 获取每一部电影详情页的url
    def get_movie_url(self,url):
        resp = requests.get(url,headers=self.headers)
        tree = lxml.html.etree.HTML(resp.text)
        m_urls = tree.xpath("//li/div/div/a/@href") 
        #获取所有li标签下的div的div的a标签名为href属性的值
        print(m_urls)
        return m_urls

    # 获取每一部电影的详细信息
    def get_movie_data(self,m_url):
        moive_page = requests.get(m_url,headers=self.headers)
        parse_movie= lxml.html.etree.HTML(moive_page.text)
        #parse_movie = moive_page.content.decode()
        return parse_movie

    # 获取每一部电影的评分,地区等详细信息
    def get_movie_data_details(self,parse_movie):
        #排名
        ranking = parse_movie.xpath("//span[@class='top250-no']/text()")
        #电影名
        name = parse_movie.xpath("//h1/span[1]/text()")
        print(name)
        #评分
        score = parse_movie.xpath("//div[@class='rating_self clearfix']/strong/text()")
        return zip(ranking, name, score)

    # 保存html网页信息
    def save_html(self,context,index):
        htmlname = "豆瓣电影top250,No.{}.html".format(index)
        with open(htmlname,'w') as f:
            f.write(context)

    # 保存为csv结构
    def save_result(self,data):
        with open('douban_top250.csv','a',encoding="utf-8-sig") as fp:
            writer = csv.writer(fp)
            writer.writerow(data)

    def run(self):
        #1.获取url
        url_list = self.get_page_url()
        for url in url_list:
            m_urls = self.get_movie_url(url)
            for m_url in m_urls:
                parse_movie = self.get_movie_data(m_url)
                data = self.get_movie_data_details(parse_movie)
                print(data)
                self.save_result(data)


        #2、获取相应
        #3、提取数据

if __name__ == "__main__":
    douban = DouBan()
    douban.run()

这是top250网页的一段源代码

"//li/div/div/a/@href"
#获取每一个电影详情页的url
        <li>
            <div class="item">
                <div class="pic">
                    <em class="">1</em>
                    <a href="https://movie.douban.com/subject/1292052/">
                        <img width="100" alt="肖申克的救赎" src="https://img3.doubanio.com/view/photo/s_ratio_poster/public/p480747492.webp" class="">
                    </a>
//div[@class='rating_self clearfix']/strong/text()
#获取每部电影的评分
<div class="rating_self clearfix" typeof="v:Rating">
    <strong class="ll rating_num" property="v:average">9.7</strong>
    <span property="v:best" content="10.0"></span>
    <div class="rating_right ">
        <div class="ll bigstar bigstar50"></div>
        <div class="rating_sum">
                <a href="collections" class="rating_people">
                    <span property="v:votes">2006192</span>人评价
                </a>
        </div>
    </div>
</div>
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值