• Jsoup-基础练习


    认识Jsoup

    一个解析网页的工具

    无论你用什么语言爬虫,都要解析网页,今天,我们用一款常用的网页解析Jsoup,来开启爬虫的第一课
    认识网页,认识爬虫,认识你自己


    快速上手

    了解一个新东西最快的方法就是频繁的使用和练习,让我们从最基础的地方开始

    • 解析一个HTML字符串
        //    使用静态Jsoup.parse(String html) 方法或 Jsoup.parse(String html, String baseUri)
            val html = "<html><head><title>First parse</title>      </head><body><p>Parsed HTML into a doc.</p></body></html>"
            val doc = Jsoup.parse(html)
            println(doc)
    
    输出如图:
    


    • 解析一个body片断
        //  使用Jsoup.parseBodyFragment(String html)
            val html ="<div><p>Lorem ipsum.</p>"
            val doc = Jsoup.parseBodyFragment(html)
            println(doc.body())
    
    输出如图:
    


    • 从一个URL加载一个Document

      示例网站,网站结构如下:

        //  使用Jsoup.parseBodyFragment(String html)
            val doc:Document = Jsoup.connect("http://example.com/").get()
            val title  = doc.title()
            println(title)
    
    输出如图:
    

    说明
    connect(String url) 方法创建一个新的 Connection, 和 get() 取得和解析一个HTML文件。如果从该URL获取HTML时发生错误,便会抛出 IOException,应适当处理

        val doc:Document = Jsoup.connect("http://example.com")  //要链接的网址
          .data("query", "Java")  //添加链接信息
          .userAgent("Mozilla")   //模拟浏览器
          .cookie("auth", "token")  //模拟cookie
          .timeout(3000)  //设置超时时长,单位ms
          .post() //链接方式
    
    

    到这里为止,你应该对Jsoup不陌生了,接下来,讲解一下爬虫中Jsoup最常用的部分

    常用方法(核心)

    解析网页的过程,其实就是一个逐级选中的过程

    讲解具体方法之前,先给大家上一个简单安全的框架:

        // 爬取的网址
        val url = "https://www.zhihu.com/explore/recommendations"
        // 加上TryCatch框架
        Try(Jsoup.connect(url).get())match {
          case Failure(e) =>
            // 打印异常信息
            println(e.getMessage)
          case Success(doc:Document) =>
            // 解析正常则返回Document,然后提取Document内所需信息
            println(doc.body())
        }
    

    有了这个框架之后,我们就可以更加肆无忌惮的调试我们的代码了
    下面我们通过知乎推荐这个网站来讲解Jsoup的核心函数

    网站URL: https://www.zhihu.com/explore/recommendations
    网页内容如下:

    我们要解析的内容如下:

    • 标题
    • 点赞
    • 作者
    • 简介

    下面我们一点一点来解析这个网页:

    • 首先是标题提取
        // 爬取的网址
        val url = "https://www.zhihu.com/explore/recommendations"
        // 加上TryCatch框架
        Try(Jsoup.connect(url).get())match {
          case Failure(e) =>
            // 打印异常信息
            println(e.getMessage)
          case Success(doc:Document) =>
            // 解析正常则返回Document,然后提取Document内所需信息
            val links = doc.select("div.zm-item") //选取class为"zm-item"的div
            for (link<-links.asScala){  //遍历每一个这样的div
              val title = link.select("h2").text()  //选取div中的所有"h2"标签,并读取它的文本内容
              println(title)  //打印标题
            }
        }
    

    输出结果如下:

    • 点赞,作者,简介的提取大同小异
    // 爬取的网址
        val url = "https://www.zhihu.com/explore/recommendations"
        // 加上TryCatch框架
        Try(Jsoup.connect(url).get())match {
          case Failure(e) =>
            // 打印异常信息
            println(e.getMessage)
          case Success(doc:Document) =>
            // 解析正常则返回Document,然后提取Document内所需信息
            val links = doc.select("div.zm-item") //选取class为"zm-item"的div
            for (link<-links.asScala){  //遍历每一个这样的div
              val title = link.select("h2").text()  //选取div中的所有"h2"标签,并读取它的文本内容
              val approve = link.select("div.zm-item-vote").text() //找到赞同的位置,选中它并读取它的文本内容
              //逐层找到唯一识别的标签,然后选中(唯一识别很关键)
              val author = link.select("div.answer-head").select("span.author-link-line").select("a").text()
    //          val content = link.select("div.zm-item-answer").select("div[data-action=/answer/content]")
    //              .select(":not(.content)").first().text()  //对比下面简洁直接的定位
              val content = link.select("div.zh-summary.summary.clearfix").text() //多个class类型,直接加.就行,如.A.B.C
    
              println("标题:"+title)  //打印标题
              println("赞同:"+approve)  //打印回答点赞数
              println("作者:"+author) //打印作者
              println("回答简介:"+content)  //打印回答简介
            }
        }
    

    ps:只要能定位到你想提取的文本,自然是越简洁越好
    有时间的话,强烈推荐跟着官网练习一下,我也只是带着你练习而已,学会阅读文档,是一项很重要的技能

    文档中是Java语法写的,如果你看的代码多了,你会发现,什么Java,scala,python,都是工具(完了完了,我膨胀了)
    最常用到的是其中的 使用选择器语法来查找元素


    结尾唠叨两句

    如果你对我的文章感兴趣,欢迎你点开我下一篇文章,后面我将手把手带你一起完成一个个小case,对了如果你也有好的想法,欢迎沟通交流
    今天的评论区强烈欢迎大家讲讲爬网站遇到的问题
    如果有种子链接,免费代爬,苍老师是世界的!


    结尾附上 使用选择器语法来查找元素 方法,以便大家快速查找

    • Selector选择器概述

      • tagname: 通过标签查找元素,比如:a
      • ns|tag: 通过标签在命名空间查找元素,比如:可以用 fb|name 语法来查找 fb:name 元素
      • id: 通过ID查找元素,比如:#logo

      • .class: 通过class名称查找元素,比如:.masthead
      • [attribute] : 利用属性查找元素,比如:[href]
      • [attr=value] : 利用属性值来查找元素,比如:[width=500]
      • [attr^=value], [attr$=value], [attr=value]: 利用匹配属性值开头、结尾或包含属性值来查找元素,比如:[href=/path/]
      • [attr~=regex]: 利用属性值匹配正则表达式来查找元素,比如: img[src~=(?i).(png|jpe?g)]
      • *: 这个符号将匹配所有元素
    • Selector选择器组合使用

      • el#id: 元素+ID,比如: div#logo
      • el.class: 元素+class,比如: div.masthead
      • el[attr]: 元素+class,比如: a[href]
      • 任意组合,比如:a[href].highlight
      • ancestor child: 查找某个元素下子元素,比如:可以用.body p 查找在"body"元素下的所有 p元素
      • parent > child: 查找某个父元素下的直接子元素,比如:可以用div.content > p 查找 p 元素,也可以用body > * 查找body标签下所有直接子元素
      • siblingA + siblingB: 查找在A元素之前第一个同级元素B,比如:div.head + div
      • siblingA ~ siblingX: 查找A元素之前的同级X元素,比如:h1 ~ p
      • el, el, el:多个选择器组合,查找匹配任一选择器的唯一元素,例如:div.masthead, div.logo
    • 伪选择器selectors

      • :lt(n): 查找哪些元素的同级索引值(它的位置在DOM树中是相对于它的父节点)小于n,比如:td:lt(3) 表示小于三列的元素
      • :gt(n):查找哪些元素的同级索引值大于n,比如: div p:gt(2)表示哪些div中有包含2个以上的p元素
      • :eq(n): 查找哪些元素的同级索引值与n相等,比如:form input:eq(1)表示包含一个input标签的Form元素
      • :has(seletor): 查找匹配选择器包含元素的元素,比如:div:has(p)表示哪些div包含了p元素
      • :not(selector): 查找与选择器不匹配的元素,比如: div:not(.logo) 表示不包含 class=logo 元素的所有 div 列表
      • :contains(text): 查找包含给定文本的元素,搜索不区分大不写,比如: p:contains(jsoup)
      • :containsOwn(text): 查找直接包含给定文本的元素
      • :matches(regex): 查找哪些元素的文本匹配指定的正则表达式,比如:div:matches((?i)login)
      • :matchesOwn(regex): 查找自身包含文本匹配指定正则表达式的元素
      • 注意:上述伪选择器索引是从0开始的,也就是说第一个元素索引值为0,第二个元素index为1等
  • 相关阅读:
    COJ979 WZJ的数据结构(负二十一)
    COJ980 WZJ的数据结构(负二十)
    奇怪的错误
    COJ883 工艺品
    COJ885 LCS???
    COJ559 回文
    hdu1505(dp求最大子矩阵)
    hdu1506(dp求最大子矩阵)
    hdu2569(递推dp)
    hdu1081(最大子矩阵)
  • 原文地址:https://www.cnblogs.com/wxplmm/p/10280918.html
Copyright © 2020-2023  润新知