`
duanhengbin
  • 浏览: 384643 次
  • 性别: Icon_minigender_1
  • 来自: 成都
社区版块
存档分类
最新评论

用Scala打造精悍爬虫(二)视频篇

 
阅读更多

【项目简述】

抓取某学院视频网站的系列课程,相比于上一篇,这一次多了不少实用性。

 

【前提】

必须要有该网站的VIP账户,主要是Cookies要使用,否则无法获取一部分受限视频。当然有不少免费获取VIP账户的方法可以自行搜索。

 

【视频网站的特点】

1)这类网站一般都有不同程度的反扒措施,某学院采用的是动态缓存,即是有权限的会员打开网页才能获取该视频的Url,这个Url有一定时效性,不适合大量抓取Url后再下载(等全抓完前面的已失效了)。但是边抓取Url边下载是没有问题的,这是较容易爬取的一类。网页的分析和以前并无分别,用F12搞定。

2)由于目标文件数量多,文件的组织比较重要,url中的文件名并不适合于文件保存(人类无法理解。。。)。这里采用最符合阅读习惯的方式对于不同层级建目录,文件名直接采用页面标题命名。另外网页上有些层级的内容未带序号,为避免下载以后排序混乱的问题,需要在前面追加序号。

3)由于目录和文件名来自网页,就会有相对于操作系统的非法字符问题,比如windows下 \/:*?"<>| 这些字符是不能出现在目录文件中的。另外还有不少其他非法文字。

4)视频文件爬取比较耗时,不要期望一次性成功,所以必须要有重复检测,即遇到已爬取的文件直接跳过。

 

先上核心代码

for( i <- 1 to 5;
     e1 <- fCrawl(url.format(i)).select("div.lesson-card");
       path1 = e1.select("h2").text.stripIllegalChar;
     (e2,j)  <- fCrawl(e1.select("div.text a").attr("href")).select("div.lesson-item").zipWithIndex;
       path2 = j + 1 + "_" +e2.select("dt.title").text.stripIllegalChar;
     e3 <- fCrawl(e2.select("a").attr("href")).select("dl.lessonvideo-list a")){
  val file = e3.text.stripIllegalChar+".mp4"
  val path = BASE_PATH + "/" + path1 + "/" + path2
  if (!(new java.io.File(path+"/"+file)).exists){
    fDownload(path, file, fCrawl(e3.attr("href")).select("source").attr("src"))
    println(s"$path\t$file\t下载成功!")
  }else{
    println(s"$path\t$file\t已下载!")
  }
}

 

是的,你没有看错,得益于Scala强大的表现力,核心代码就只有这10几行。当然还没有把一些辅助型代码算在内。

 

说明:

  • 首先是Scala的for语句实际上是一个可用于多层次迭代的语法糖,上面的语句实际上产生了四层迭代。第一层 1 to 5 是对分页的迭代,后面每一层进入一次页面抓取,最后循环体内的fcrawl就可以抓取到视频Url了。类似如下结构:

(1 to 5)

  .foreach(i => fCrawl(url.format(i)).select("div.lesson-card") )

    .foreach( e1 => fCrawl(e1.select("div.text a").attr("href")).select("div.lesson-item").zipWithIndex)

      .foreach( (e2,j) => fCrawl(e2.select("a").attr("href")).select("dl.lessonvideo-list a")))))

 

  • e2级中,zipWithIndex这个方法是用来给迭代对象添加序号的,由于Scala的序号从0开始,所以使用的时候还需要加1。
  • 熟悉Scala的朋友一定会问,stripIllegalChar是什么鬼,居然用在了String类型上。这个其实是Scala的黑科技之一隐式类,很多时候,它能让代码更加优雅。

真相在这里

implicit class StringImprovement(val s : String){
    // 删除文件名中的非法字符
  def stripIllegalChar = s.replaceAll("???", "").replaceAll("\\\\|/|:|\\*|\\?|<|>|\\||\"", "")
}

 

现在String类型的对象就可以使用stripIllegalChar方法去删除那些非法字符了。???是特指一些无法显示的非法字符,这个只能遇到的时候,现去添加,由于该程序有重复文件判断,所以每次异常修改后,直接再次执行就好了。

 

fCrawl,fDownload这两个方法就是简单递归自身保证Url抓取和文件下载的成功。

def fCrawl(url: String): Document = 
  Try(Jsoup.connect(url).timeout(0).cookies(cookies).get()) match {
    case Failure(e) => println(e.getMessage); sleep(10000); fCrawl(url)
    case Success(d) => d
  }

def fDownload(path: String, file: String, url: String): Unit =
  Try(JavaHelper.download(path, file, url)) match {
    case Failure(e) => println(e.getMessage); sleep(10000); JavaHelper.download(path, file, url)
    case Success(_) =>
  }

 

异常的时候三步:异常信息打印,暂停10秒,再次执行。

 

 

最后是JavaHelper.download方法,由于jsoup下载文件的能力较差,自己写了一个java方法如下(实际运行下来发现还蛮健壮,极少出错):

public static void download(String path, String fileName, String fileUrl) throws IOException {
    File pathFile = new File(path); 
    if (!pathFile.exists()) {
        pathFile.mkdirs();
    }
      
    URL url = new URL(fileUrl);
    InputStream inStream = url.openConnection().getInputStream();
    FileOutputStream fs = new FileOutputStream(path + "/" + fileName);

    byte[] buffer = new byte[1204];
    int byteread = 0;
    while ((byteread = inStream.read(buffer)) != -1) {
        fs.write(buffer, 0, byteread);
    }
    fs.close();
}

 

其他代码

// Url源
val url = "http://ke.jikexueyuan.com/xilie/?page=%d"
// 存储路径
val BASE_PATH = "G:/video/Series"

def sleep(i: Long) = Thread.sleep(i)
// 这里设置你的vip账户的cookies信息,用F12你应该懂的
val cookies = new java.util.HashMap[String,String]
cookies.put("uname", "???") 
cookies.put("authcode", "???") 

 

经过累计时间差不多1天的半值守运行,成功下载了带有良好目录结构的3000+视频文件。

 

小结: Scala的很多特性(如类型推断,隐式转换,众多语法糖等等),让它变成一门极高“信噪比”的语言。显然,更少的代码,会让维护都变得更容易。但同时,灵活掌握这些特性也有一定难度,我想这也许是它始终无法普及的原因吧。

0
5
分享到:
评论

相关推荐

    scala实战高清讲解

    - 隐式转换:Scala允许隐式参数和隐式转换,有助于代码简洁性,但需谨慎使用以避免混淆。 - 类型推断:Scala具有强大的类型推断能力,允许编写更少的类型声明,提高代码可读性。 - 泛型:泛型提供了一种方式来...

    基于Scala语言的Webmagicx爬虫框架设计源码

    该项目为基于Scala语言的Webmagicx爬虫框架设计源码,包含136个文件,涵盖67个Java文件、47个Scala文件、8个HTML文件、3个属性文件、3个XML文件、2个sbt文件、2个批处理文件、2个Shell脚本文件、1个Git忽略文件以及1...

    Scala程序设计第二版

    《Scala程序设计第二版》是美国作家Dean Wampler和Alex Payne合作的作品,由人民邮电出版社出版,并由王渊和陈明翻译成中文,于2016年3月发行,共500页。这本书深入浅出地介绍了Scala编程语言,是学习Scala语言的...

    scala sdk scala-2.12.3

    通过学习和使用Scala SDK,开发者可以利用其丰富的语言特性来构建复杂的软件系统,尤其是在大数据处理、Web应用、云计算等领域,Scala已经展现出了强大的生命力。例如Apache Spark,一个流行的分布式计算框架,就是...

    scala3 scala3 scala3 scala3 scala3

    Scala3,也被称为Scala 3或Dotty,是Scala编程语言的一个重大更新,旨在提高其简洁性、可读性和类型安全性。Scala3的发布标志着该语言的进一步成熟,它引入了一系列改进,旨在解决早期版本中的一些痛点,同时保持对...

    scala编程 第二版

    经典scala教程 This book is a tutorial for the Scala programming language, written by people directly involved in the development of Scala. Our goal is that by reading this book, you can learn ...

    scala编程 第二版(高清+书签)

    Scala编程第二版是一本深受读者喜爱的编程指南,豆瓣评分高达8.0,这足以证明其在编程领域的权威性和实用性。Scala是一种多范式编程语言,融合了面向对象和函数式编程的特点,使得它在处理大数据和分布式计算时,如...

    Scala.pdf中文高清第二版

    8. **FP与OOP的结合**:Scala巧妙地将面向对象和函数式编程融合在一起,使得开发者可以根据需求选择最适合的编程范式,或者混合使用两者。 9. **交互式编程**:Scala的REPL(Read-Eval-Print Loop)环境允许开发者...

    Scala语法简明教程

    - Udemy上的《Scala and Akka Microservices》:教授如何使用Scala和Akka框架构建微服务。 - **社区与论坛**: - Scala官方网站([http://www.scala-lang.org](http://www.scala-lang.org/)):提供了大量的文档...

    最新整理的大数据scala和spark视频教程

    在这个视频教程中,你将能够学习到如何使用Scala进行基本编程,理解其语法和特性。同时,你会深入到Spark的世界,学习如何创建Spark应用程序,理解RDD(弹性分布式数据集)、DataFrame和DataSet的概念,以及如何在...

    scala + mybatis 数据库查询

    通过使用Scala的Java互操作性,我们可以无缝地在Scala中使用MyBatis。 - 集成步骤通常包括添加MyBatis和其Scala绑定库到项目依赖,配置MyBatis的SqlSessionFactory,并编写Scala版的Mapper接口。 2. **Scala版的...

    快学 Scala(第二版) Second Edition

    **快学 Scala(第二版)** Scala是一种多范式编程语言,它融合了面向对象编程和函数式编程的特性,由Martin Odersky在2003年设计并推出。《快学 Scala(第二版)》是专为希望快速掌握Scala编程的读者编写的指南,尤其...

    scala学习视频&pdf;讲义

    scala学习视频资料以及讲义,从基础的环境配置开始讲起,以及后面具体案例开发.适合新手学习,还有具体讲义对照复习查看。

    使用Scala进行Web开发:构建你的第一个Web应用.md

    使用Scala进行Web开发使用Scala进行Web开发使用Scala进行Web开发使用Scala进行Web开发使用Scala进行Web开发使用Scala进行Web开发使用Scala进行Web开发使用Scala进行Web开发使用Scala进行Web开发使用Scala进行Web开发...

    scala学习源代码

    Scala是一种强大的多范式编程语言,它融合了面向对象和函数式编程的特性。这个"scala学习源代码"的压缩包文件很可能包含了用于教学或自我学习Scala编程的基础示例。让我们深入了解一下Scala语言的关键概念和特性。 ...

    Scala语言视频百度网盘

    第01阶段 :Scala 入门 第02阶段:Scala 的函数式编程 第03阶段:Scala 的面向对象编程 第04阶段:Scala的高级基础一 第05阶段:Scala的高级基础二

    Scala函数式编程

    1 scala用起来比java更灵活 2 强大的collection,可以更加方便的处理collection类的数据 3 不同于java的并行处理方法,有点像c的逻辑思路 4 开发成本比java小,但是语言学习成本比java高很多 正在阅读这本书的...

    scala API 操作hbase表

    在本文中,我们将深入探讨如何使用Scala API操作HBase数据库。HBase是一个分布式、面向列的NoSQL数据库,它构建于Hadoop之上,提供实时访问大量数据的能力。Scala是一种强大的函数式编程语言,与Java虚拟机(JVM)...

Global site tag (gtag.js) - Google Analytics