`
duanhengbin
  • 浏览: 385313 次
  • 性别: 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语言的Webmagicx爬虫框架设计源码

    sbt文件的存在说明项目使用了Scala的构建工具sbt来进行项目的构建和管理。批处理文件和Shell脚本文件则可能用于项目的一些自动化操作和部署。Git忽略文件表明该项目遵循了版本控制的优秀实践,而Markdown文件则为...

    scala实战高清讲解

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

    Scala程序设计第二版

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

    Scala语法简明教程

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

    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 sdk scala-2.12.3

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

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

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

    Scala.pdf中文高清第二版

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

    最新整理的大数据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