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 语法来查找 元素
    • id: 通过ID查找元素,比如:#logo

    • .class: 通过class名称查找元素,比如:.masthead
    • [attribute] : 利用属性查找元素,比如:[href]
    • [attr=value] : 利用属性值来查找元素,比如:[width=500]
    • [attr^=value], [attr$=value], [attr*=value]: 利用匹配属性值开头、结尾或包含属性值来查找元素,比如:[href*=/path/]
    • *: 这个符号将匹配所有元素
  • 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等
posted @ 2019-01-17 10:36 wxplmm 阅读(...) 评论(...) 编辑 收藏