wordpress 点击图片跳转,seo顾问服,wordpress装主题失败,微信网站怎么做的好简单使用Scala和Jsoup对豆瓣电影进行爬虫#xff0c;技术比較简单易学。写文章不易#xff0c;欢迎大家採我的文章#xff0c;以及给出实用的评论#xff0c;当然大家也能够关注一下我的github#xff1b;多谢。 1、爬虫前期准备 找好须要抓取的链接#xff1a;https://m… 简单使用Scala和Jsoup对豆瓣电影进行爬虫技术比較简单易学。 写文章不易欢迎大家採我的文章以及给出实用的评论当然大家也能够关注一下我的github多谢。 1、爬虫前期准备 找好须要抓取的链接https://movie.douban.com/tag/%E7%BB%8F%E5%85%B8?start20typeT 观看该链接的源代码找到须要进行解析的地方如本实例图中标明了须要提取的字段。 下载Jsoup的jar包文件https://jsoup.org/download建立Scalaproject并将Jsoup的jar包增加project2、Jsoup简介 Jsoup学习请看这个网址jsoup Cookbook(中文版)http://www.open-open.com/jsoup/ 我这里仅仅介绍我用到了的四个函数 1、第一个函数Jsoup.connect(url)
val doc:DocumentJsoup.connect(url).get()//从一个站点获取和解析一个HTML文档,使用get方式。说的直白点这里获得的就是网页的源代码 //特殊使用带有參数并使用Post方式 Document doc Jsoup.connect(http://example.com) .data(query, Java) .userAgent(Mozilla) .cookie(auth, token) .timeout(3000) .post(); 2、第二个函数Element.select(String selector) doc.select(a.nbg)//通过使用CSS或Jqueryselector syntax 获得你想要操作元素这里获得的是说有classnbg的a/标签。 3、第三个函数public String attr(String attributeKey) Elements中的attr函数是通过属性获得Element中第一个匹配该属性的值。如elem.select(a.nbg).attr(title)获得a标签中的title。 4、第四个函数public String html() 获得element中包括的Html内容 3、解析Html 这里的Html内容比較简单。仅仅须要获得如图一中标记的四处。这里仅仅要用到第二章中的后面三个方法。 //解析Document须要对比网页源代码进行解析
def parseDoc(doc: Document, movies: ConcurrentHashMap[String, String]) {var count 0for (elem - doc.select(tr.item)) {//获得全部的电影条目movies.put(elem.select(a.nbg).attr(title), elem.select(a.nbg).attr(title) \t //标题 elem.select(a.nbg).attr(href) \t //豆瓣链接// elem.select(p.pl).html\t//简介 elem.select(span.rating_nums).html \t //评分 elem.select(span.pl).html //评论数)count 1}count
} 4、建立连接获得相应Url的Html 这里使用了Scala中的Try语法我这里仅仅简单说明当Jsoup.connect(url).get() 返回异常时模式匹配会匹配Failure(e)并将异常赋值给模板类中的e。当返回成功时将匹配Success(doc)并将获得的Html的Document赋值给doc。 //用于记录总数。和失败次数
val sum, fail: AtomicInteger new AtomicInteger(0)
/*** 当出现异常时10s后重试,异常反复100次* param delay延时时间* param url抓取的Url* param movies存取抓到的内容*/
def requestGetUrl(times: Int 100, delay: Long 10000)(url: String, movies: ConcurrentHashMap[String, String]): Unit {Try(Jsoup.connect(url).get()) match {//使用try来推断是否成功和失败对网页进行抓取case Failure(e) if (times ! 0) {println(e.getMessage)fail.addAndGet(1)Thread.sleep(delay)requestGetUrl(times - 1, delay)(url, movies)} else throw ecase Success(doc) val count parseDoc(doc, movies);if (count 0) {Thread.sleep(delay);requestGetUrl(times - 1, delay)(url, movies)}sum.addAndGet(count);}
} 5、使用并发集合 为了加快住区速度使用了Scala中的并发集合par。相似于java中的fork/join框架 /*** 多线程抓取* param url:原始的Url* param tag电影标签* param maxPage页数* param threadNum线程数* param movies并发集合存取抓到的内容*/
def concurrentCrawler(url: String, tag: String, maxPage: Int, threadNum: Int, movies: ConcurrentHashMap[String, String]) {val loopPar (0 to maxPage).parloopPar.tasksupport new ForkJoinTaskSupport(new ForkJoinPool(threadNum)) // 设置并发线程数loopPar.foreach(i requestGetUrl()(url.format(URLEncoder.encode(tag, UTF-8), 20 * i), movies)) // 利用并发集合多线程同步抓取:遍历全部页saveFile1(tag, movies)//保存为文件
} 6、运行任务 想要进行爬虫仅仅须要这样调用concurrentCrawler(URL, tag, page, Thread_Num, new ConcurrentHashMapString, String)函数即可。 def main(args: Array[String]): Unit {val Thread_Num 30 //指定并发运行线程数val t1 System.currentTimeMillisfor ((tag, page) - tags)concurrentCrawler(URL, tag, page, Thread_Num, new ConcurrentHashMap[String, String]())//并发抓取val t2 System.currentTimeMillisprintln(s抓取数$sum 重试数$fail 耗时(秒) (t2 - t1) / 1000)}
} 运行结果 抓取数793 重试数0 耗时(秒)4 本文来自伊豚wpeace(blog.wpeace.cn) 7、全部代码 import java.io.{File, PrintWriter}
import java.net.URLEncoder
import java.text.SimpleDateFormat
import java.util.Date
import java.util.concurrent.ConcurrentHashMap
import java.util.concurrent.atomic.AtomicIntegerimport org.jsoup.Jsoup
import org.jsoup.nodes.Documentimport scala.collection.JavaConversions._
import scala.collection.mutable.ArrayBuffer
import scala.collection.parallel.ForkJoinTaskSupport
import scala.concurrent.forkjoin.ForkJoinPool
import scala.util.{Failure, Success, Try}/*** Created by peace on 2017/3/5.*/
object Douban {val URL https://movie.douban.com/tag/%s?start%dtypeT //訪问的链接 //须要抓取的标签和页数 val tags Map( 经典 - 4, //tag页数 爱情 - 4, 动作 - 4, 剧情 - 4, 悬疑 - 4, 文艺 - 4, 搞笑 - 4, 战争 - 4 ) //解析Document须要对比网页源代码进行解析 def parseDoc(doc: Document, movies: ConcurrentHashMap[String, String]) { var count 0 for (elem - doc.select(tr.item)) { movies.put(elem.select(a.nbg).attr(title), elem.select(a.nbg).attr(title) \t //标题 elem.select(a.nbg).attr(href) \t //豆瓣链接 // elem.select(p.pl).html\t//简介 elem.select(span.rating_nums).html \t //评分 elem.select(span.pl).html //评论数 ) count 1 } count } //用于记录总数。和失败次数 val sum, fail: AtomicInteger new AtomicInteger(0) /** * 当出现异常时10s后重试,异常反复100次 * param delay延时时间 * param url抓取的Url * param movies存取抓到的内容 */ def requestGetUrl(times: Int 100, delay: Long 10000)(url: String, movies: ConcurrentHashMap[String, String]): Unit { Try(Jsoup.connect(url).get()) match {//使用try来推断是否成功和失败对网页进行抓取 case Failure(e) if (times ! 0) { println(e.getMessage) fail.addAndGet(1) Thread.sleep(delay) requestGetUrl(times - 1, delay)(url, movies) } else throw e case Success(doc) val count parseDoc(doc, movies); if (count 0) { Thread.sleep(delay); requestGetUrl(times - 1, delay)(url, movies) } sum.addAndGet(count); } } /** * 多线程抓取 * param url:原始的Url * param tag电影标签 * param maxPage页数 * param threadNum线程数 * param movies并发集合存取抓到的内容 */ def concurrentCrawler(url: String, tag: String, maxPage: Int, threadNum: Int, movies: ConcurrentHashMap[String, String]) { val loopPar (0 to maxPage).par loopPar.tasksupport new ForkJoinTaskSupport(new ForkJoinPool(threadNum)) // 设置并发线程数 loopPar.foreach(i requestGetUrl()(url.format(URLEncoder.encode(tag, UTF-8), 20 * i), movies)) // 利用并发集合多线程同步抓取:遍历全部页 saveFile1(tag, movies) } //直接输出 def saveFile(file: String, movies: ConcurrentHashMap[String, String]) { val writer new PrintWriter(new File(new SimpleDateFormat(yyyyMMdd).format(new Date()) _ file .txt)) for ((_, value) - movies) writer.println(value) writer.close() } // 排序输出到文件 def saveFile1(file: String, movies: ConcurrentHashMap[String, String]) { val writer new PrintWriter(new File(new SimpleDateFormat(yyyyMMdd).format(new Date()) _ file .txt)) val col new ArrayBuffer[String](); for ((_, value) - movies) col value; val sort col.sortWith( (o1, o2) { val s1 o1.split(\t)(2); val s2 o2.split(\t)(2); if (s1 null || s2 null || s1.isEmpty || s2.isEmpty) { true } else { s1.toFloat s2.toFloat } } ) sort.foreach(writer.println(_)) writer.close() } def main(args: Array[String]): Unit { val Thread_Num 30 //指定并发运行线程数 val t1 System.currentTimeMillis for ((tag, page) - tags) concurrentCrawler(URL, tag, page, Thread_Num, new ConcurrentHashMap[String, String]())//并发抓取 val t2 System.currentTimeMillis println(s抓取数$sum 重试数$fail 耗时(秒) (t2 - t1) / 1000) } } 转载于:https://www.cnblogs.com/llguanli/p/8398170.html