(2 из 2)      << | < | 1 | 2 | > | >>
package sape

object Parser {

  def part(s: String, left: Char = '"', right: Char = '"') = {
    val k = s.indexOf(left)
    val n = s.lastIndexOf(right)
    s.slice(k+1,if (n>k) n else s.length)
  }

  def parseArray(s: String): Map[String, Any] = {
    parse(part(s,'{','}'))
  }

  def value(s: String) = {
    val a = s.split(':')
    a.head match { // a - Array, s -String, i - Int, d - Float, b - Boolean
      case "a" => parseArray(s)
      case _ => part(s)
    }
  }

  def toTuple(a: Array[String]) = {
    if (a.length == 2) {
      part(a.head) -> value(a.last)
    } else "" -> ""
  }

  def parse (s: String) = {
    if (s.head == 'a') parseArray(s) 
    else toParts(s).grouped(2).map(a => toTuple(a)).filter(x => x._1 != "").toMap
  }

  def levels(s: String) = {
    var i = 0
    s.map(c => {
      i += (if (c=='{') 1 else if (c=='}') -1 else 0)
      i
    })
  }

  def toParts(s: String) = {
    val a = (s.indices zip levels(s)).filter(p => (s(p._1)==';') && (p._2==0)).map((p => p._1))
    ((Array(-1) ++ a) zip (a ++ Array(s.length))).map(x => s.slice(x._1+1,x._2))
  }
}

import java.net.URL
import java.util.Date
import scala.io.Source

object Sape {
  val servers = List("dispenser-01.sape.ru", "dispenser-02.sape.ru")
  var user = "sape_user_code"
  var host = "localhost"
  def url = "/code.php?user="+user+"&host="+host+"&charset=UTF-8"
  var raw = Map[String,Any]()
  var time: Long = 0

  def getUrl(url: String) = {
    try {
      val con = new URL(url).openConnection
      con.setConnectTimeout(1000)
      con.setReadTimeout(1000)
      Source.fromInputStream(con.getInputStream).mkString("")
    } catch { case _:Throwable => ""}
  }

  def data = {
    val s = getUrl("http://"+servers(0)+url)
    (if (s != "") s else  getUrl("http://"+servers(1)+url)).replaceAll("\";}","\"};")
  }

  def update = {
    val t = (new Date).getTime
    if (t - time > 1000*60*5) {
      raw = Parser.parse(data)
      time = t
    }
  }

  def f(a: Iterable[Any], b: Boolean) = if (b) Seq("") ++ a ++ Seq("") else a

  def get(uri: String, robot: Boolean) = {
    update
    val u = raw.getOrElse(uri,"")
    f(if (u != "") {
      u match {
        case m: Map[_,_] => m.values
        case _ => Seq[Any]()
      }
    } else {
      val nu = raw.getOrElse("__sape_new_url__","")
      nu match {
        case m: Map[_,_] => m.values
        case _ => Seq[Any](nu)
      }
    },robot).mkString(raw.getOrElse("__sape_delimiter__"," ").toString)
  }
}

Объект Sape при вызове метода get обновляет переменную raw, если после последнего обновления прошло более 5 минут. В get передаются два аргумента: путь на веб-страницу от корня (типа "/my/good/page") и логическое значение robot (true, если страницу запросил робот от sape.ru).

Если нет желания возиться с исходниками, то можно просто скачать уже готовую к использованию (скомпилированную и собранную для jvm) библиотеку sape.jar.

Пример ее использования из scala:

import sape.Sape
 Sape.user = "6а5df ... e169" // нужно присвоить ваш код пользователя
 Sape.host = "my.site.ru" // нужно присвоить ваш host
 // пример вызова из фреймворка Play2 (ссылки для страницы)
 Sape.get(request.uri,request.cookies.get("sape_cookie").getOrElse("")==Sape.user)

Пример ее использования из java:

import sape.Sape;
 Sape.user_$eq("6а5df ... e169"); // нужно присвоить ваш код пользователя
 Sape.host_$eq("my.site.ru"); // нужно присвоить ваш host
 boolean isRobot = getCookieValue(request.getCookies(),"sape_cookie").equals(Sape.user());
 Sape.get(request.getRequestURI(), isRobot) // ссылки для страницы

 private String getCookieValue(Cookie[] cookies, String name) {
   if (cookies == null) return "";
   for (Cookie cookie: cookies)
     if ( cookie.getName().equals(name) ) return cookie.getValue();
   return "";
 }
(2 из 2)      << | < | 1 | 2 | > | >>

Комментарии (0)

Автор (*):Город:
Эл.почта:Сайт:
Текст (*):