Created
October 30, 2009 08:34
-
-
Save yuroyoro/222221 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import java.net.{Authenticator, PasswordAuthentication} | |
import scala.Math._ | |
import scala.xml._ | |
import scala.io.Source | |
object TwitterListRecommender{ | |
val url ="http://twitter.com/%s/lists/memberships.xml" | |
// Usage : scala TwitterListRecommender <your_id> <your_password> | |
def main(args:Array[String]) = { | |
val Array( userid, passwd ) = args | |
// Basic認証 | |
Authenticator.setDefault( | |
new Authenticator { | |
override def getPasswordAuthentication = | |
new PasswordAuthentication( userid, passwd.toCharArray) | |
} | |
) | |
// 登録されているListを取得する | |
val source = Source.fromURL( url.format( userid) ) | |
val xml = XML.loadString( source.getLines.mkString ) | |
val lists = xml \\ "list" | |
// Listの購読者数から標準偏差を算出 | |
val sd = { | |
val cnts = lists.map{ l => (l \ "subscriber_count" text ).toDouble + 1} | |
val total = (0.0 /: cnts ){ _ + _} | |
val ave = total / lists.size | |
cnts.map{ i => pow( i - ave , 2) }.foldLeft( 0.0 ){ _ + _ } / cnts.size | |
} | |
// followしているidを取得 | |
val ids = { | |
val src = Source.fromURL( "http://twitter.com/friends/ids/%s.xml".format( userid )) | |
val idxml = XML.loadString( src.getLines.mkString ) | |
(idxml \\ "id").map( _ text ) | |
} | |
// Listから集計 | |
( Map.empty[String, Double] /: lists ){ (m,l) => | |
// (購読者数 + 1)/標準偏差 * 100 がweight | |
val weight = (( l \ "subscriber_count" text ).toDouble + 1) / sd * 100 | |
// Listのmemberを取得する | |
val src = Source.fromURL( "http://twitter.com%s/members.xml".format( l \ "uri" text )) | |
val lxml = XML.loadString( src.getLines.mkString ) | |
// すでにfollowしているIDはのぞく | |
( lxml \\ "user").filter{ | |
user => ids.exists( _ == (user \ "id" text) ) == false | |
}.foldLeft( m ){ | |
(mm , user) => { | |
val name = user \ "screen_name" text ; | |
mm + ( name -> ( mm.getOrElse( name ,0.0 ) + weight )) | |
} | |
} | |
}.toList.sort{ case( (_, v1), (_, v2) )=> v1 > v2 }.foreach{ | |
case ( name, v ) => println( "%-30s : %.4f ".format( name, v)) | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment