wuclan 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/LICENSE.textile +20 -0
- data/README.textile +28 -0
- data/examples/analyze/strong_links/gen_multi_edge.rb +103 -0
- data/examples/analyze/strong_links/main.rb +51 -0
- data/examples/analyze/word_count/dump_schema.rb +13 -0
- data/examples/analyze/word_count/freq_user.rb +31 -0
- data/examples/analyze/word_count/freq_whole_corpus.rb +27 -0
- data/examples/analyze/word_count/word_count.pig +43 -0
- data/examples/analyze/word_count/word_count.rb +34 -0
- data/examples/lastfm/scrape/load_lastfm.rb +31 -0
- data/examples/lastfm/scrape/scrape_lastfm.rb +47 -0
- data/examples/lastfm/scrape/seed.tsv +147 -0
- data/examples/twitter/old/load_twitter_search_jobs.rb +157 -0
- data/examples/twitter/old/scrape_twitter_api.rb +104 -0
- data/examples/twitter/old/scrape_twitter_search.rb +57 -0
- data/examples/twitter/old/scrape_twitter_trending.rb +73 -0
- data/examples/twitter/parse/parse_twitter_requests.rb +81 -0
- data/examples/twitter/parse/parse_twitter_search_requests.rb +28 -0
- data/examples/twitter/scrape_twitter_api/scrape_twitter_api.rb +61 -0
- data/examples/twitter/scrape_twitter_api/seed.tsv +4 -0
- data/examples/twitter/scrape_twitter_api/start_cache_twitter.sh +2 -0
- data/examples/twitter/scrape_twitter_api/support/make_request_stats.rb +291 -0
- data/examples/twitter/scrape_twitter_api/support/make_requests_by_id_and_date_1.rb +98 -0
- data/examples/twitter/scrape_twitter_api/support/make_requests_by_id_and_date_2.pig +4 -0
- data/examples/twitter/scrape_twitter_api/support/twitter_search_jobs.tsv +6 -0
- data/examples/twitter/scrape_twitter_api/support/twitter_trending_seed.tsv +725 -0
- data/examples/twitter/scrape_twitter_hosebird/edamame-killall +4 -0
- data/examples/twitter/scrape_twitter_hosebird/foo.rb +19 -0
- data/examples/twitter/scrape_twitter_hosebird/ps_emulation.rb +111 -0
- data/examples/twitter/scrape_twitter_hosebird/scrape_twitter_hosebird.rb +110 -0
- data/examples/twitter/scrape_twitter_hosebird/test_spewer.rb +20 -0
- data/examples/twitter/scrape_twitter_hosebird/twitter_hosebird_god.yaml +10 -0
- data/examples/twitter/scrape_twitter_search/dump_twitter_search_jobs.rb +38 -0
- data/examples/twitter/scrape_twitter_search/load_twitter_search_jobs.rb +63 -0
- data/examples/twitter/scrape_twitter_search/scrape_twitter_search.rb +44 -0
- data/examples/twitter/scrape_twitter_search/twitter_search_daemons.god +25 -0
- data/lib/old/twitter_api.rb +88 -0
- data/lib/wuclan/delicious/delicious_html_request.rb +31 -0
- data/lib/wuclan/delicious/delicious_models.rb +26 -0
- data/lib/wuclan/delicious/delicious_request.rb +65 -0
- data/lib/wuclan/friendfeed/scrape/friendfeed_search_request.rb +60 -0
- data/lib/wuclan/friendster.rb +7 -0
- data/lib/wuclan/lastfm/model/base.rb +49 -0
- data/lib/wuclan/lastfm/model/sample_responses.txt +16 -0
- data/lib/wuclan/lastfm/scrape/base.rb +195 -0
- data/lib/wuclan/lastfm/scrape/concrete.rb +143 -0
- data/lib/wuclan/lastfm/scrape/lastfm_job.rb +12 -0
- data/lib/wuclan/lastfm/scrape/lastfm_request_stream.rb +17 -0
- data/lib/wuclan/lastfm/scrape/recursive_requests.rb +154 -0
- data/lib/wuclan/lastfm/scrape.rb +12 -0
- data/lib/wuclan/lastfm.rb +7 -0
- data/lib/wuclan/metrics/user_graph_metrics.rb +99 -0
- data/lib/wuclan/metrics/user_metrics.rb +443 -0
- data/lib/wuclan/metrics/user_metrics_basic.rb +277 -0
- data/lib/wuclan/metrics/user_scraping_metrics.rb +64 -0
- data/lib/wuclan/metrics.rb +0 -0
- data/lib/wuclan/myspace.rb +21 -0
- data/lib/wuclan/open_social/model/base.rb +0 -0
- data/lib/wuclan/open_social/scrape/base.rb +111 -0
- data/lib/wuclan/open_social/scrape_request.rb +6 -0
- data/lib/wuclan/open_social.rb +0 -0
- data/lib/wuclan/rdf_output/relationship_rdf.rb +47 -0
- data/lib/wuclan/rdf_output/text_element_rdf.rb +64 -0
- data/lib/wuclan/rdf_output/tweet_rdf.rb +10 -0
- data/lib/wuclan/rdf_output/twitter_rdf.rb +84 -0
- data/lib/wuclan/rdf_output/twitter_user_rdf.rb +12 -0
- data/lib/wuclan/shorturl/shorturl_request.rb +271 -0
- data/lib/wuclan/twitter/api_response_examples.textile +300 -0
- data/lib/wuclan/twitter/model/base.rb +72 -0
- data/lib/wuclan/twitter/model/multi_edge.rb +31 -0
- data/lib/wuclan/twitter/model/relationship.rb +176 -0
- data/lib/wuclan/twitter/model/text_element/extract_info_tests.rb +83 -0
- data/lib/wuclan/twitter/model/text_element/grok_tweets.rb +96 -0
- data/lib/wuclan/twitter/model/text_element/more_regexes.rb +370 -0
- data/lib/wuclan/twitter/model/text_element.rb +38 -0
- data/lib/wuclan/twitter/model/tweet/tokenize.rb +38 -0
- data/lib/wuclan/twitter/model/tweet/tweet_regexes.rb +202 -0
- data/lib/wuclan/twitter/model/tweet/tweet_token.rb +79 -0
- data/lib/wuclan/twitter/model/tweet.rb +74 -0
- data/lib/wuclan/twitter/model/twitter_user/style/color_to_hsv.rb +57 -0
- data/lib/wuclan/twitter/model/twitter_user.rb +145 -0
- data/lib/wuclan/twitter/model.rb +21 -0
- data/lib/wuclan/twitter/parse/ff_ids_parser.rb +27 -0
- data/lib/wuclan/twitter/parse/friends_followers_parser.rb +52 -0
- data/lib/wuclan/twitter/parse/generic_json_parser.rb +26 -0
- data/lib/wuclan/twitter/parse/json_tweet.rb +63 -0
- data/lib/wuclan/twitter/parse/json_twitter_user.rb +122 -0
- data/lib/wuclan/twitter/parse/public_timeline_parser.rb +54 -0
- data/lib/wuclan/twitter/parse/twitter_search_parse.rb +60 -0
- data/lib/wuclan/twitter/parse/user_parser.rb +30 -0
- data/lib/wuclan/twitter/scrape/base.rb +97 -0
- data/lib/wuclan/twitter/scrape/old_skool_request_classes.rb +40 -0
- data/lib/wuclan/twitter/scrape/twitter_fake_fetcher.rb +31 -0
- data/lib/wuclan/twitter/scrape/twitter_ff_ids_request.rb +75 -0
- data/lib/wuclan/twitter/scrape/twitter_followers_request.rb +135 -0
- data/lib/wuclan/twitter/scrape/twitter_json_response.rb +124 -0
- data/lib/wuclan/twitter/scrape/twitter_request_stream.rb +44 -0
- data/lib/wuclan/twitter/scrape/twitter_search_fake_fetcher.rb +44 -0
- data/lib/wuclan/twitter/scrape/twitter_search_flat_stream.rb +30 -0
- data/lib/wuclan/twitter/scrape/twitter_search_job.rb +25 -0
- data/lib/wuclan/twitter/scrape/twitter_search_request.rb +70 -0
- data/lib/wuclan/twitter/scrape/twitter_search_request_stream.rb +19 -0
- data/lib/wuclan/twitter/scrape/twitter_timeline_request.rb +72 -0
- data/lib/wuclan/twitter/scrape/twitter_user_request.rb +64 -0
- data/lib/wuclan/twitter/scrape.rb +27 -0
- data/lib/wuclan/twitter.rb +7 -0
- data/lib/wuclan.rb +1 -0
- data/spec/spec_helper.rb +9 -0
- data/spec/wuclan_spec.rb +7 -0
- data/wuclan.gemspec +184 -0
- metadata +219 -0
@@ -0,0 +1,60 @@
|
|
1
|
+
# module Wuclan
|
2
|
+
# module Twitter
|
3
|
+
# module Scrape
|
4
|
+
# #
|
5
|
+
# # ScrapeRequest for the twitter Search API.
|
6
|
+
# #
|
7
|
+
# # Examines the parsed contents to describe result
|
8
|
+
# #
|
9
|
+
# class TwitterSearchRequest < Monkeyshines::ScrapeRequest
|
10
|
+
# include Monkeyshines::RawJsonContents
|
11
|
+
# # Extract the actual search items returned
|
12
|
+
# def items
|
13
|
+
# parsed_contents['results'] if parsed_contents
|
14
|
+
# end
|
15
|
+
# # Checks that the response parses and has the right data structure.
|
16
|
+
# # if healthy? is true things should generally work
|
17
|
+
# def healthy?
|
18
|
+
# items && items.is_a?(Array)
|
19
|
+
# end
|
20
|
+
# # Number of items returned in this request
|
21
|
+
# def num_items()
|
22
|
+
# items ? items.length : 0
|
23
|
+
# end
|
24
|
+
# # Span of IDs. Assumes the response has the ids in sort order oldest to newest
|
25
|
+
# # (which the twitter API provides)
|
26
|
+
# def span
|
27
|
+
# [items.last['id'], items.first['id']] rescue nil
|
28
|
+
# end
|
29
|
+
# # Span of created_at times covered by this request.
|
30
|
+
# # Useful for rate estimation.
|
31
|
+
# def timespan
|
32
|
+
# [Time.parse(items.last['created_at']), Time.parse(items.first['created_at'])] rescue nil
|
33
|
+
# end
|
34
|
+
# end
|
35
|
+
# end
|
36
|
+
# end
|
37
|
+
# end
|
38
|
+
# end
|
39
|
+
|
40
|
+
|
41
|
+
|
42
|
+
# class FriendFeedSearchFetcher
|
43
|
+
# def search_url query, page, max_id
|
44
|
+
# start = (page-1)*100
|
45
|
+
# %Q{http://friendfeed.com/api/feed/search?q=#{query}&service=twitter&start=#{start}&num=100}
|
46
|
+
# end
|
47
|
+
# def max_results_per_page
|
48
|
+
# 100
|
49
|
+
# end
|
50
|
+
# def max_page
|
51
|
+
# 4
|
52
|
+
# end
|
53
|
+
# def terminate? response, page
|
54
|
+
# terminate = super || page >= max_page
|
55
|
+
# end
|
56
|
+
# def get_results response
|
57
|
+
# response['entries'] if response
|
58
|
+
# end
|
59
|
+
# end
|
60
|
+
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'monkeyshines/scrape_request/raw_json_contents'
|
2
|
+
module Wuclan
|
3
|
+
module Lastfm
|
4
|
+
|
5
|
+
class LastfmUser
|
6
|
+
end
|
7
|
+
|
8
|
+
class LastfmShout
|
9
|
+
end
|
10
|
+
|
11
|
+
class LastfmArtist
|
12
|
+
end
|
13
|
+
|
14
|
+
class LastfmAlbum
|
15
|
+
end
|
16
|
+
|
17
|
+
class LastfmTrack
|
18
|
+
end
|
19
|
+
|
20
|
+
class LastfmGroup
|
21
|
+
end
|
22
|
+
|
23
|
+
class LastfmTag
|
24
|
+
end
|
25
|
+
|
26
|
+
class LastfmEvent
|
27
|
+
end
|
28
|
+
|
29
|
+
class LastfmVenue
|
30
|
+
end
|
31
|
+
|
32
|
+
# Interactions
|
33
|
+
|
34
|
+
class AShoutsB
|
35
|
+
end
|
36
|
+
|
37
|
+
# Relationships
|
38
|
+
|
39
|
+
class LastfmTagging < Struct.new(:user_id, :taggable_type, :taggable_id)
|
40
|
+
end
|
41
|
+
|
42
|
+
class LastfmListen
|
43
|
+
end
|
44
|
+
|
45
|
+
class LastfmAttending
|
46
|
+
end
|
47
|
+
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
// lastfm_artist_info_request Linkin%20Park 1 http://ws.audioscrobbler.com/2.0/?method=Artist.getInfo&artist=Linkin%20Park&limit=100&page=1&api_key=12717a7e1a0ec8a053026b813fd59a7c&format=json 20090817020535 200 OK
|
2
|
+
{ "artist": {
|
3
|
+
"name": "Linkin Park",
|
4
|
+
"mbid": "f59c5520-5f46-4d2c-b2c4-822eabf53419",
|
5
|
+
"stats": {"listeners":"1473188","playcount":"93021323"},
|
6
|
+
"url": "http:\/\/www.last.fm\/music\/Linkin+Park",
|
7
|
+
"tags": {"tag":[{"name":"rock","url":"http:\/\/www.last.fm\/tag\/rock"},{"name":"nu metal","url":"http:\/\/www.last.fm\/tag\/nu%20metal"},{"name":"alternative","url":"http:\/\/www.last.fm\/tag\/alternative"},{"name":"alternative rock","url":"http:\/\/www.last.fm\/tag\/alternative%20rock"},{"name":"metal","url":"http:\/\/www.last.fm\/tag\/metal"}]},
|
8
|
+
"bio": {"published":"Thu, 2 Jul 2009 21:19:19 +0000","summary":"Linkin Park is a band from Agoura Hills, California. The band consists of Joe "<a href=\"http:\/\/ws.audioscrobbler.com\/music\/Mr.+Hahn\" class=\"bbcode_artist\">Mr. Hahn<\/a>" Hahn, <a href=\"http:\/\/ws.audioscrobbler.com\/music\/Mike+Shinoda\" class=\"bbcode_artist\">Mike Shinoda<\/a>, Dave Farrell (a.k.a. Phoenix), <a href=\"http:\/\/ws.audioscrobbler.com\/music\/Chester+Bennington\" class=\"bbcode_artist\">Chester Bennington<\/a>, <a href=\"http:\/\/ws.audioscrobbler.com\/music\/Brad+Delson\" class=\"bbcode_artist\">Brad Delson<\/a> and <a href=\"http:\/\/ws.audioscrobbler.com\/music\/Rob+Bourdon\" class=\"bbcode_artist\">Rob Bourdon<\/a>. Released under the band name "Hybrid Theory", the band's first album, <a title=\"Linkin Park - Hybrid Theory EP\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/Hybrid+Theory+EP\" class=\"bbcode_album\">Hybrid Theory EP<\/a> was released in 1995. Only 1000 copies of this very rare original EP were made. The band's first full studio album, <a title=\"Linkin Park - Hybrid Theory\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/Hybrid+Theory\" class=\"bbcode_album\">Hybrid Theory<\/a>, released in 2001, had a huge success, selling 42 million copies worldwide as of October 2009.","content":"<strong>Linkin Park<\/strong> is a band from Agoura Hills, California. The band consists of Joe "<a href=\"http:\/\/ws.audioscrobbler.com\/music\/Mr.+Hahn\" class=\"bbcode_artist\">Mr. Hahn<\/a>" Hahn, <a href=\"http:\/\/ws.audioscrobbler.com\/music\/Mike+Shinoda\" class=\"bbcode_artist\">Mike Shinoda<\/a>, Dave Farrell (a.k.a. Phoenix), <a href=\"http:\/\/ws.audioscrobbler.com\/music\/Chester+Bennington\" class=\"bbcode_artist\">Chester Bennington<\/a>, <a href=\"http:\/\/ws.audioscrobbler.com\/music\/Brad+Delson\" class=\"bbcode_artist\">Brad Delson<\/a> and <a href=\"http:\/\/ws.audioscrobbler.com\/music\/Rob+Bourdon\" class=\"bbcode_artist\">Rob Bourdon<\/a>.\n \n Released under the band name "Hybrid Theory", the band's first album, <a title=\"Linkin Park - Hybrid Theory EP\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/Hybrid+Theory+EP\" class=\"bbcode_album\">Hybrid Theory EP<\/a> was released in 1995. Only 1000 copies of this very rare original EP were made.\n \n The band's first full studio album, <a title=\"Linkin Park - Hybrid Theory\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/Hybrid+Theory\" class=\"bbcode_album\">Hybrid Theory<\/a>, released in 2001, had a huge success, selling 42 million copies worldwide as of October 2009. Among its singles were <a title=\"Linkin Park – One Step Closer\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/_\/One+Step+Closer\" class=\"bbcode_track\">One Step Closer<\/a>, <a title=\"Linkin Park – Crawling\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/_\/Crawling\" class=\"bbcode_track\">Crawling<\/a>, and the band's highest-selling single, <a title=\"Linkin Park – In the End\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/_\/In+the+End\" class=\"bbcode_track\">In the End<\/a>. In 2001, the band released "Frat party at the pancake festival". A dvd with live stuff, extra footage of the band and the music video's from Hybrid Theory. A remix album, <a title=\"Linkin Park - Reanimation\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/Reanimation\" class=\"bbcode_album\">Reanimation<\/a> was released in 2002, and was based around Hybrid Theory songs.\n \n The band's second studio album, <a title=\"Linkin Park - Meteora\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/Meteora\" class=\"bbcode_album\">Meteora<\/a> (released 2003), was not so successful as "Hybrid Theory". Still, it sold 10 million copies worldwide, spawned the worldwide hit <a title=\"Linkin Park – Breaking the Habit\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/_\/Breaking+the+Habit\" class=\"bbcode_track\">Breaking the Habit<\/a>, and was the first Linkin Park album that was not fully rap driven.\n \n A limited edition live album and DVD came next: <a title=\"Linkin Park - Live in Texas\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/Live+in+Texas\" class=\"bbcode_album\">Live in Texas<\/a>. It was an opportunity for fans who have not been to the band's gigs to see their performance live. \n \n Linkin Park and <a href=\"http:\/\/ws.audioscrobbler.com\/music\/Jay-Z\" class=\"bbcode_artist\">Jay-Z<\/a> then released <a title=\"Jay-Z and Linkin Park - Collision Course\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Jay-Z+and+Linkin+Park\/Collision+Course\" class=\"bbcode_album\">Collision Course<\/a> in which previously-released songs from the two artists were mixed together. Some time after this was a major label attempt to combat the success of illegal <a href=\"http:\/\/ws.audioscrobbler.com\/tag\/mashup\" class=\"bbcode_tag\" rel=\"tag\">mashup<\/a> albums popular in 2004 and 2005, most of which also used Jay-Z's <a title=\"Jay-Z - Black Album\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Jay-Z\/Black+Album\" class=\"bbcode_album\">Black Album<\/a> a cappellas. The album introduced fans of both artists to each other and marked the beginning of Jay-Z's return from retirement.\n \n The band's newest album is <a title=\"Linkin Park - Minutes To Midnight\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/Minutes+To+Midnight\" class=\"bbcode_album\">Minutes To Midnight<\/a>, often abbreviated MTM. The album was co-produced by Mike Shinoda and legendary Grammy wining producer Rick Rubin (Slayer, Red Hot Chili Peppers, Johnny Cash) The release date, originally somewhere between July and September of 2006, was pushed to May of 2007. The band cites their reasoning as having fun experimenting with new styles and sounds in the studio, saying it was their most fun recording session to date. The new album was finally released on iTunes on May 11th 2007 and in stores worldwide three days later. The sounds are new, more hip-hop based beats and rock song dynamics. It is 12 tracks long, including the band's 6th consecutive #1 hit, <a title=\"Linkin Park – What I've Done\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/_\/What+I%27ve+Done\" class=\"bbcode_track\">What I've Done<\/a>. The video for the song was directed by Joseph Hahn.\n \n Four more singles from Minutes to Midnight were released: \n <a title=\"Linkin Park – Bleed It Out\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/_\/Bleed+It+Out\" class=\"bbcode_track\">Bleed It Out<\/a> (released August 2007), <a title=\"Linkin Park – Shadow of the Day\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/_\/Shadow+of+the+Day\" class=\"bbcode_track\">Shadow of the Day<\/a> (released October 2007), <a title=\"Linkin Park – Given Up\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/_\/Given+Up\" class=\"bbcode_track\">Given Up<\/a> (released March 2008), and the final single, <a title=\"Linkin Park – Leave Out All the Rest\" href=\"http:\/\/ws.audioscrobbler.com\/music\/Linkin+Park\/_\/Leave+Out+All+the+Rest\" class=\"bbcode_track\">Leave Out All the Rest<\/a> (released June 2008).\n \n The band began touring again in late April in 2007 with a show in Berlin, and then continuing through Europe. 2007 also marks the return of the Projekt Revolution tour, which is always headlined by Linkin Park.\n \n On 29 June 2008, the band played their biggest Projekt Revolution show to date at the Milton Keynes Bowl, the venue Green Day's 2005 live DVD was recorded at (a 60,000+ capacity venue). The PR UK lineup included Jay-Z who again performed some "Collision Course" tracks with Linkin Park. Other bands included Pendulum, N*E*R*D, Enter Shikari, The Bravery and Innerpartysystem.\n \n The band's second live CD\/DVD, Road To Revolution: Live At Milton Keynes, was released November 24th 2008. It included at least one song of each Linkin Park album including Collision Course with Jay-Z and featured excerpts from Fort Minor's The Rising Tied in Points Of Authority. "}}}
|
9
|
+
"image": [{"#text":"http:\/\/userserve-ak.last.fm\/serve\/34\/21871115.jpg","size":"small"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/64\/21871115.jpg","size":"medium"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/126\/21871115.jpg","size":"large"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/252\/21871115.jpg","size":"extralarge"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/_\/21871115\/Linkin+Park.jpg","size":"mega"}],"streamable":"1",
|
10
|
+
"similar": {
|
11
|
+
"artist":[
|
12
|
+
{"name":"Fort Minor","url":"http:\/\/www.last.fm\/music\/Fort+Minor","image":[{"#text":"http:\/\/userserve-ak.last.fm\/serve\/34\/108914.jpg","size":"small"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/64\/108914.jpg>","size":"medium"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/126\/108914.jpg","size":"large"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/252\/108914.jpg","size":"extralarge"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/500\/108914\/Fort+Minor.jpg","size":"mega"}]},
|
13
|
+
{"name":"Jay-Z and Linkin Park","url":"http:\/\/www.last.fm\/music\/Jay-Z+and+Linkin+Park","image":[{"#text":"http:\/\/userserve-ak.last.fm\/serve\/34\/16170933.jpg","size":"small"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/64\/16170933.jpg>","size":"medium"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/126\/16170933.jpg","size":"large"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/252\/16170933.jpg","size":"extralarge"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/500\/16170933\/JayZ+and+Linkin+Park+LP++JAYZ.jpg","size":"mega"}]},
|
14
|
+
{"name":"Chester Bennington","url":"http:\/\/www.last.fm\/music\/Chester+Bennington","image":[{"#text":"http:\/\/userserve-ak.last.fm\/serve\/34\/33909.jpg","size":"small"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/64\/33909.jpg>","size":"medium"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/126\/33909.jpg","size":"large"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/252\/33909.jpg","size":"extralarge"},{"#text":"","size":"mega"}]},
|
15
|
+
{"name":"Xero","url":"http:\/\/www.last.fm\/music\/Xero","image":[{"#text":"http:\/\/userserve-ak.last.fm\/serve\/34\/8582695.jpg","size":"small"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/64\/8582695.jpg>","size":"medium"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/126\/8582695.jpg","size":"large"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/252\/8582695.jpg","size":"extralarge"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/500\/8582695\/Xero.jpg","size":"mega"}]},
|
16
|
+
{"name":"Papa Roach","url":"http:\/\/www.last.fm\/music\/Papa+Roach", "image":[{"#text":"http:\/\/userserve-ak.last.fm\/serve\/34\/23013493.jpg","size":"small"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/64\/23013493.jpg>","size":"medium"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/126\/23013493.jpg","size":"large"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/252\/23013493.jpg","size":"extralarge"},{"#text":"http:\/\/userserve-ak.last.fm\/serve\/500\/23013493\/Papa+Roach+lifeline_presspic.jpg","size":"mega"}]}]},
|
@@ -0,0 +1,195 @@
|
|
1
|
+
require 'monkeyshines/scrape_request/raw_json_contents'
|
2
|
+
module Wuclan
|
3
|
+
module Lastfm
|
4
|
+
module Scrape
|
5
|
+
|
6
|
+
#
|
7
|
+
# Base class for Lastfm API requests
|
8
|
+
#
|
9
|
+
#
|
10
|
+
# For parsing, note the different form for empty responses.
|
11
|
+
#
|
12
|
+
class Base < TypedStruct.new(
|
13
|
+
[:identifier, Integer],
|
14
|
+
[:page, Integer],
|
15
|
+
[:moreinfo, String],
|
16
|
+
[:url, String],
|
17
|
+
[:scraped_at, Bignum],
|
18
|
+
[:response_code, Integer],
|
19
|
+
[:response_message, String],
|
20
|
+
[:contents, String]
|
21
|
+
)
|
22
|
+
# Basic ScrapeRequest functionality
|
23
|
+
include Monkeyshines::ScrapeRequestCore
|
24
|
+
# Contents are JSON
|
25
|
+
include Monkeyshines::RawJsonContents
|
26
|
+
# API Authentication
|
27
|
+
cattr_accessor :api_key
|
28
|
+
self.api_key = Monkeyshines::CONFIG[:lastfm_api][:api_key] rescue nil
|
29
|
+
|
30
|
+
#
|
31
|
+
# call with fields in order:
|
32
|
+
#
|
33
|
+
# identifier page moreinfo url scraped_at response_code response_message contents
|
34
|
+
#
|
35
|
+
# you only have to fill in what you know -- in fact, it's typical to
|
36
|
+
# pass in only the identifier
|
37
|
+
def initialize *args
|
38
|
+
super *args
|
39
|
+
self.page = (page.to_i < 1 ? 1 : page.to_i)
|
40
|
+
end
|
41
|
+
|
42
|
+
# ===========================================================================
|
43
|
+
#
|
44
|
+
# API
|
45
|
+
#
|
46
|
+
|
47
|
+
# Slug for the URL to let lastfm know what resource is requested
|
48
|
+
class_inheritable_accessor :api_method
|
49
|
+
# Responses are a JSON hash with one
|
50
|
+
class_inheritable_accessor :main_fieldname
|
51
|
+
class_inheritable_accessor :response_type
|
52
|
+
|
53
|
+
#
|
54
|
+
# Generate request URL from other attributes
|
55
|
+
#
|
56
|
+
def make_url
|
57
|
+
[ "http://ws.audioscrobbler.com/2.0/?method=#{api_method}#{identifier}",
|
58
|
+
"&limit=#{max_items}&api_key=#{self.class.api_key}&format=json",
|
59
|
+
"&page=#{page}" ].join("")
|
60
|
+
end
|
61
|
+
|
62
|
+
#
|
63
|
+
# Call with a hash of identifier attr-val pairs (including an optional page)
|
64
|
+
#
|
65
|
+
# Ex.
|
66
|
+
# LastfmAlbumInfoRequest.from_identifier_hash(
|
67
|
+
# :album => 'Rum+Sodomy+%26+the+Lash',
|
68
|
+
# :artist => 'The+Pogues',
|
69
|
+
# :mbid => 'ba1f6641-9085-36a0-8962-65ad6e48afd1')
|
70
|
+
# Calls
|
71
|
+
# LastfmAlbumInfoRequest.new(
|
72
|
+
# 'album=Rum+Sodomy+%26+the+Lash&artist=The+Pogues&mbid=ba1f6641-9085-36a0-8962-65ad6e48afd1')
|
73
|
+
#
|
74
|
+
# FIXME -- this is stupid in taking a special 'id' and a just-as-necessary hash
|
75
|
+
#
|
76
|
+
def self.from_identifier_hash name, hsh={}
|
77
|
+
name = url_encode(name)
|
78
|
+
page = hsh.delete(:page)
|
79
|
+
rest = self.class.make_url_query(hsh)
|
80
|
+
new("#{name}&#{rest}", page)
|
81
|
+
end
|
82
|
+
|
83
|
+
# ===========================================================================
|
84
|
+
#
|
85
|
+
# Parsing
|
86
|
+
#
|
87
|
+
|
88
|
+
# Healthy if it's well-formed and not an error
|
89
|
+
def healthy?
|
90
|
+
super && ( (contents !~ %r{^\{"error":}) )
|
91
|
+
end
|
92
|
+
|
93
|
+
#
|
94
|
+
# Last.fm responses typically have the form
|
95
|
+
#
|
96
|
+
# { "requested_objs": {
|
97
|
+
# "requested_type": [ { ... obj ... }, { ... obj ... } ... ],
|
98
|
+
# "@attr":{ "key": "val" }
|
99
|
+
# }
|
100
|
+
# }
|
101
|
+
#
|
102
|
+
# e.g.
|
103
|
+
#
|
104
|
+
# {"similarartists":{
|
105
|
+
# "artist": [
|
106
|
+
# ...
|
107
|
+
# {"name":"Pillar","mbid":"..","match":"5.66",..."streamable":"1"}],
|
108
|
+
# "@attr":{"artist":"Dead by Sunrise"}
|
109
|
+
# }}
|
110
|
+
#
|
111
|
+
def main_result
|
112
|
+
return @main_result if @main_result
|
113
|
+
return unless healthy?
|
114
|
+
@main_result = parsed_contents[main_fieldname] rescue {}
|
115
|
+
end
|
116
|
+
|
117
|
+
#
|
118
|
+
# Information about the request itself.
|
119
|
+
#
|
120
|
+
# (see doc for result_attrs)
|
121
|
+
def result_attrs
|
122
|
+
main_result["@attr"] rescue {}
|
123
|
+
end
|
124
|
+
|
125
|
+
# Extract the actual search items returned
|
126
|
+
def items
|
127
|
+
# [obj_or_array].flatten makes this always be an array (lastfm gives
|
128
|
+
# the single object when it's not an array)
|
129
|
+
[main_result[response_type]].flatten.compact rescue []
|
130
|
+
end
|
131
|
+
|
132
|
+
#
|
133
|
+
# Pagination and Rescheduling
|
134
|
+
#
|
135
|
+
# Pagination
|
136
|
+
include Monkeyshines::ScrapeRequestCore::Paginated
|
137
|
+
include Monkeyshines::ScrapeRequestCore::Paginating
|
138
|
+
include Monkeyshines::ScrapeRequestCore::PaginatedWithLimit
|
139
|
+
# include Monkeyshines::ScrapeRequestCore::PaginatedWithRate
|
140
|
+
|
141
|
+
# API max items per response
|
142
|
+
self.max_items = 50
|
143
|
+
# API max pages
|
144
|
+
self.hard_request_limit = 15
|
145
|
+
# Items to get each re-visit. If there are up to 50 items per page,
|
146
|
+
# target_items_per_job of 1000 will try to reschedule so that its return visit
|
147
|
+
# makes about twenty page requests.
|
148
|
+
# #self.target_items_per_job = 150
|
149
|
+
|
150
|
+
# creates the paginated request
|
151
|
+
def request_for_page page, pageinfo=nil
|
152
|
+
(page.to_i > 1) ? self.class.new(identifier, page) : self
|
153
|
+
end
|
154
|
+
|
155
|
+
#
|
156
|
+
# Max pages for this resource
|
157
|
+
#
|
158
|
+
def max_pages
|
159
|
+
return 1 if (result_attrs.blank? || result_attrs['totalPages'].blank?)
|
160
|
+
attrs['totalPages'].to_i.clamp(1,self.hard_request_limit)
|
161
|
+
end
|
162
|
+
|
163
|
+
#
|
164
|
+
# For stream-type objects
|
165
|
+
#
|
166
|
+
|
167
|
+
# Span of IDs. Assumes the response has the ids in sort order oldest to newest
|
168
|
+
# (which the twitter API provides)
|
169
|
+
def span
|
170
|
+
[items.last['id'], items.first['id']] rescue nil
|
171
|
+
end
|
172
|
+
# Span of created_at times covered by this request.
|
173
|
+
# Useful for rate estimation.
|
174
|
+
def timespan
|
175
|
+
[Time.parse(items.last['created_at']).utc, Time.parse(items.first['created_at']).utc] rescue nil
|
176
|
+
end
|
177
|
+
|
178
|
+
class_inheritable_accessor :requestables
|
179
|
+
self.requestables = []
|
180
|
+
def recursive_requests &block
|
181
|
+
return unless healthy?
|
182
|
+
#
|
183
|
+
# requestables
|
184
|
+
#
|
185
|
+
requestables.each do |klass|
|
186
|
+
req = klass.new(identifier)
|
187
|
+
req.generation = generation.to_i + 1
|
188
|
+
yield req
|
189
|
+
end
|
190
|
+
end
|
191
|
+
end
|
192
|
+
|
193
|
+
end
|
194
|
+
end
|
195
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
module Wuclan
|
2
|
+
module Lastfm
|
3
|
+
module Scrape
|
4
|
+
|
5
|
+
#
|
6
|
+
# Defines the concrete terms of the API
|
7
|
+
#
|
8
|
+
|
9
|
+
class LastfmAlbumInfoRequest < Base ; self.api_method = 'album.getinfo&album=' ; end
|
10
|
+
class LastfmAlbumTagsRequest < Base ; self.api_method = 'album.gettags&album=' ; end
|
11
|
+
class LastfmArtistEventsRequest < Base ; self.api_method = 'artist.getevents&artist=' ; end
|
12
|
+
class LastfmArtistImagesRequest < Base ; self.api_method = 'artist.getimages&artist=' ; end
|
13
|
+
class LastfmArtistInfoRequest < Base ; self.api_method = 'artist.getinfo&artist=' ; end
|
14
|
+
class LastfmArtistPodcastRequest < Base ; self.api_method = 'artist.getpodcast&artist=' ; end
|
15
|
+
class LastfmArtistShoutsRequest < Base ; self.api_method = 'artist.getshouts&artist=' ; end
|
16
|
+
class LastfmArtistSimilarRequest < Base ; self.api_method = 'artist.getsimilar&artist=' ; end
|
17
|
+
class LastfmArtistTagsRequest < Base ; self.api_method = 'artist.gettags&artist=' ; end
|
18
|
+
class LastfmArtistTopAlbumsRequest < Base ; self.api_method = 'artist.gettopalbums&artist=' ; end
|
19
|
+
class LastfmArtistTopFansRequest < Base ; self.api_method = 'artist.gettopfans&artist=' ; end
|
20
|
+
class LastfmArtistTopTagsRequest < Base ; self.api_method = 'artist.gettoptags&artist=' ; end
|
21
|
+
class LastfmArtistTopTracksRequest < Base ; self.api_method = 'artist.gettoptracks&artist=' ; end
|
22
|
+
class LastfmEventAttendeesRequest < Base ; self.api_method = 'event.getattendees&event=' ; end
|
23
|
+
class LastfmEventInfoRequest < Base ; self.api_method = 'event.getinfo&event=' ; end
|
24
|
+
class LastfmEventShoutsRequest < Base ; self.api_method = 'event.getshouts&event=' ; end
|
25
|
+
class LastfmGeoEventsRequest < Base ; self.api_method = 'geo.getevents&geo=' ; end
|
26
|
+
class LastfmGeoTopArtistsRequest < Base ; self.api_method = 'geo.gettopartists&geo=' ; end
|
27
|
+
class LastfmGeoTopTracksRequest < Base ; self.api_method = 'geo.gettoptracks&geo=' ; end
|
28
|
+
class LastfmGroupMembersRequest < Base ; self.api_method = 'group.getmembers&group=' ; end
|
29
|
+
class LastfmGroupWeeklyAlbumChartRequest < Base ; self.api_method = 'group.getweeklyalbumchart&group=' ; end
|
30
|
+
class LastfmGroupWeeklyArtistChartRequest < Base ; self.api_method = 'group.getweeklyartistchart&group=' ; end
|
31
|
+
class LastfmGroupWeeklyChartListRequest < Base ; self.api_method = 'group.getweeklychartlist&group=' ; end
|
32
|
+
class LastfmGroupWeeklyTrackChartRequest < Base ; self.api_method = 'group.getweeklytrackchart&group=' ; end
|
33
|
+
class LastfmPlaylistfetchRequest < Base ; self.api_method = 'playlist.fetch&playlist=' ; end
|
34
|
+
class LastfmTagSimilarRequest < Base ; self.api_method = 'tag.getsimilar&tag=' ; end
|
35
|
+
class LastfmTagTopAlbumsRequest < Base ; self.api_method = 'tag.gettopalbums&tag=' ; end
|
36
|
+
class LastfmTagTopArtistsRequest < Base ; self.api_method = 'tag.gettopartists&tag=' ; end
|
37
|
+
class LastfmTagTopTagsRequest < Base ; self.api_method = 'tag.gettoptags&tag=' ; end
|
38
|
+
class LastfmTagTopTracksRequest < Base ; self.api_method = 'tag.gettoptracks&tag=' ; end
|
39
|
+
class LastfmTagWeeklyArtistChartRequest < Base ; self.api_method = 'tag.getweeklyartistchart&tag=' ; end
|
40
|
+
class LastfmTagWeeklyChartListRequest < Base ; self.api_method = 'tag.getweeklychartlist&tag=' ; end
|
41
|
+
class LastfmTasteometercompareRequest < Base ; self.api_method = 'tasteometer.compare&tasteometer=' ; end
|
42
|
+
class LastfmTrackInfoRequest < Base ; self.api_method = 'track.getinfo&track=' ; end
|
43
|
+
class LastfmTrackSimilarRequest < Base ; self.api_method = 'track.getsimilar&track=' ; end
|
44
|
+
class LastfmTrackTagsRequest < Base ; self.api_method = 'track.gettags&track=' ; end
|
45
|
+
class LastfmTrackTopFansRequest < Base ; self.api_method = 'track.gettopfans&track=' ; end
|
46
|
+
class LastfmTrackTopTagsRequest < Base ; self.api_method = 'track.gettoptags&track=' ; end
|
47
|
+
class LastfmUserEventsRequest < Base ; self.api_method = 'user.getevents&user=' ; end
|
48
|
+
class LastfmUserFriendsRequest < Base ; self.api_method = 'user.getfriends&recenttracks=1&user=' ; end
|
49
|
+
class LastfmUserInfoRequest < Base ; self.api_method = 'user.getinfo&user=' ; end
|
50
|
+
class LastfmUserLovedTracksRequest < Base ; self.api_method = 'user.getlovedtracks&user=' ; end
|
51
|
+
class LastfmUserNeighboursRequest < Base ; self.api_method = 'user.getneighbours&user=' ; end
|
52
|
+
class LastfmUserPastEventsRequest < Base ; self.api_method = 'user.getpastevents&user=' ; end
|
53
|
+
class LastfmUserPlaylistsRequest < Base ; self.api_method = 'user.getplaylists&user=' ; end
|
54
|
+
class LastfmUserRecentStationsRequest < Base ; self.api_method = 'user.getrecentstations&user=' ; end
|
55
|
+
class LastfmUserRecentTracksRequest < Base ; self.api_method = 'user.getrecenttracks&user=' ; end
|
56
|
+
class LastfmUserRecommendedArtistsRequest < Base ; self.api_method = 'user.getrecommendedartists&user=' ; end
|
57
|
+
class LastfmUserRecommendedEventsRequest < Base ; self.api_method = 'user.getrecommendedevents&user=' ; end
|
58
|
+
class LastfmUserShoutsRequest < Base ; self.api_method = 'user.getshouts&user=' ; end
|
59
|
+
class LastfmUserTopAlbumsRequest < Base ; self.api_method = 'user.gettopalbums&user=' ; end
|
60
|
+
class LastfmUserTopArtistsRequest < Base ; self.api_method = 'user.gettopartists&user=' ; end
|
61
|
+
class LastfmUserTopTagsRequest < Base ; self.api_method = 'user.gettoptags&user=' ; end
|
62
|
+
class LastfmUserTopTracksRequest < Base ; self.api_method = 'user.gettoptracks&user=' ; end
|
63
|
+
class LastfmUserWeeklyAlbumChartRequest < Base ; self.api_method = 'user.getweeklyalbumchart&user=' ; end
|
64
|
+
class LastfmUserWeeklyArtistChartRequest < Base ; self.api_method = 'user.getweeklyartistchart&user=' ; end
|
65
|
+
class LastfmUserWeeklyChartListRequest < Base ; self.api_method = 'user.getweeklychartlist&user=' ; end
|
66
|
+
class LastfmUserWeeklyTrackChartRequest < Base ; self.api_method = 'user.getweeklytrackchart&user=' ; end
|
67
|
+
class LastfmVenueEventsRequest < Base ; self.api_method = 'venue.getevents&venue=' ; end
|
68
|
+
class LastfmVenuePastEventsRequest < Base ; self.api_method = 'venue.getpastevents&venue=' ; end
|
69
|
+
|
70
|
+
# Singular
|
71
|
+
class LastfmAlbumInfoRequest < Base ; self.main_fieldname = 'album' ; self.response_type = 'album' ; end
|
72
|
+
class LastfmArtistInfoRequest < Base ; self.main_fieldname = 'artist' ; self.response_type = 'artist' ; end
|
73
|
+
class LastfmEventInfoRequest < Base ; self.main_fieldname = 'event' ; self.response_type = 'event' ; end
|
74
|
+
class LastfmTrackInfoRequest < Base ; self.main_fieldname = 'track' ; self.response_type = 'track' ; end
|
75
|
+
class LastfmUserInfoRequest < Base ; self.main_fieldname = 'user' ; self.response_type = 'user' ; end
|
76
|
+
# Albums
|
77
|
+
class LastfmArtistTopAlbumsRequest < Base ; self.main_fieldname = 'topalbums' ; self.response_type = 'album' ; end
|
78
|
+
class LastfmTagTopAlbumsRequest < Base ; self.main_fieldname = 'topalbums' ; self.response_type = 'album' ; end
|
79
|
+
class LastfmUserTopAlbumsRequest < Base ; self.main_fieldname = 'topalbums' ; self.response_type = 'album' ; end
|
80
|
+
# Tracks
|
81
|
+
class LastfmArtistTopTracksRequest < Base ; self.main_fieldname = 'toptracks' ; self.response_type = 'track' ; end
|
82
|
+
class LastfmGeoTopTracksRequest < Base ; self.main_fieldname = 'toptracks' ; self.response_type = 'track' ; end
|
83
|
+
class LastfmTagTopTracksRequest < Base ; self.main_fieldname = 'toptracks' ; self.response_type = 'track' ; end
|
84
|
+
class LastfmUserTopTracksRequest < Base ; self.main_fieldname = 'toptracks' ; self.response_type = 'track' ; end
|
85
|
+
class LastfmUserLovedTracksRequest < Base ; self.main_fieldname = 'lovedtracks' ; self.response_type = 'track' ; end
|
86
|
+
class LastfmUserRecentTracksRequest < Base ; self.main_fieldname = 'recenttracks' ; self.response_type = 'track' ; end
|
87
|
+
class LastfmTrackSimilarRequest < Base ; self.main_fieldname = 'similartracks' ; self.response_type = 'track' ; end
|
88
|
+
# Artists
|
89
|
+
class LastfmArtistSimilarRequest < Base ; self.main_fieldname = 'artists' ; self.response_type = 'artist' ; end
|
90
|
+
class LastfmUserRecommendedArtistsRequest < Base ; self.main_fieldname = 'recommendedartists' ; self.response_type = 'artist' ; end
|
91
|
+
class LastfmGeoTopArtistsRequest < Base ; self.main_fieldname = 'topartists' ; self.response_type = 'artist' ; end
|
92
|
+
class LastfmTagTopArtistsRequest < Base ; self.main_fieldname = 'topartists' ; self.response_type = 'artist' ; end
|
93
|
+
class LastfmUserTopArtistsRequest < Base ; self.main_fieldname = 'topartists' ; self.response_type = 'artist' ; end
|
94
|
+
# Events
|
95
|
+
class LastfmArtistEventsRequest < Base ; self.main_fieldname = 'events' ; self.response_type = 'event' ; end
|
96
|
+
class LastfmGeoEventsRequest < Base ; self.main_fieldname = 'events' ; self.response_type = 'event' ; end
|
97
|
+
class LastfmUserEventsRequest < Base ; self.main_fieldname = 'events' ; self.response_type = 'event' ; end
|
98
|
+
class LastfmVenueEventsRequest < Base ; self.main_fieldname = 'events' ; self.response_type = 'event' ; end
|
99
|
+
class LastfmUserPastEventsRequest < Base ; self.main_fieldname = 'pastevents' ; self.response_type = 'event' ; end
|
100
|
+
class LastfmVenuePastEventsRequest < Base ; self.main_fieldname = 'pastevents' ; self.response_type = 'event' ; end
|
101
|
+
class LastfmUserRecommendedEventsRequest < Base ; self.main_fieldname = 'recommendedevents' ; self.response_type = 'event' ; end
|
102
|
+
# Users
|
103
|
+
class LastfmEventAttendeesRequest < Base ; self.main_fieldname = 'attendees' ; self.response_type = 'user' ; end
|
104
|
+
class LastfmUserFriendsRequest < Base ; self.main_fieldname = 'friends' ; self.response_type = 'user' ; end
|
105
|
+
class LastfmArtistTopFansRequest < Base ; self.main_fieldname = 'topfans' ; self.response_type = 'user' ; end
|
106
|
+
class LastfmTrackTopFansRequest < Base ; self.main_fieldname = 'topfans' ; self.response_type = 'user' ; end
|
107
|
+
class LastfmGroupMembersRequest < Base ; self.main_fieldname = 'members' ; self.response_type = 'user' ; end
|
108
|
+
class LastfmUserNeighboursRequest < Base ; self.main_fieldname = 'neighbours' ; self.response_type = 'user' ; end
|
109
|
+
# Shouts
|
110
|
+
class LastfmArtistShoutsRequest < Base ; self.main_fieldname = 'shouts' ; self.response_type = 'shout' ; end
|
111
|
+
class LastfmEventShoutsRequest < Base ; self.main_fieldname = 'shouts' ; self.response_type = 'shout' ; end
|
112
|
+
class LastfmUserShoutsRequest < Base ; self.main_fieldname = 'shouts' ; self.response_type = 'shout' ; end
|
113
|
+
# Tags
|
114
|
+
class LastfmArtistTagsRequest < Base ; self.main_fieldname = 'similartags' ; self.response_type = 'tag' ; end
|
115
|
+
class LastfmTagSimilarRequest < Base ; self.main_fieldname = 'similartags' ; self.response_type = 'tag' ; end
|
116
|
+
class LastfmAlbumTagsRequest < Base ; self.main_fieldname = 'tags' ; self.response_type = 'tag' ; end
|
117
|
+
class LastfmTrackTagsRequest < Base ; self.main_fieldname = 'tags' ; self.response_type = 'tag' ; end
|
118
|
+
class LastfmArtistTopTagsRequest < Base ; self.main_fieldname = 'toptags' ; self.response_type = 'tag' ; end
|
119
|
+
class LastfmTagTopTagsRequest < Base ; self.main_fieldname = 'toptags' ; self.response_type = 'tag' ; end
|
120
|
+
class LastfmTrackTopTagsRequest < Base ; self.main_fieldname = 'toptags' ; self.response_type = 'tag' ; end
|
121
|
+
class LastfmUserTopTagsRequest < Base ; self.main_fieldname = 'toptags' ; self.response_type = 'tag' ; end
|
122
|
+
# Charts
|
123
|
+
class LastfmGroupWeeklyAlbumChartRequest < Base ; self.main_fieldname = 'weeklyalbumchart' ; self.response_type = 'weeklyalbumchart' ; end
|
124
|
+
class LastfmUserWeeklyAlbumChartRequest < Base ; self.main_fieldname = 'weeklyalbumchart' ; self.response_type = 'weeklyalbumchart' ; end
|
125
|
+
class LastfmGroupWeeklyArtistChartRequest < Base ; self.main_fieldname = 'weeklyartistchart' ; self.response_type = 'weeklyartistchart' ; end
|
126
|
+
class LastfmTagWeeklyArtistChartRequest < Base ; self.main_fieldname = 'weeklyartistchart' ; self.response_type = 'weeklyartistchart' ; end
|
127
|
+
class LastfmUserWeeklyArtistChartRequest < Base ; self.main_fieldname = 'weeklyartistchart' ; self.response_type = 'weeklyartistchart' ; end
|
128
|
+
class LastfmGroupWeeklyChartListRequest < Base ; self.main_fieldname = 'weeklychartlist' ; self.response_type = 'weeklychartlist' ; end
|
129
|
+
class LastfmTagWeeklyChartListRequest < Base ; self.main_fieldname = 'weeklychartlist' ; self.response_type = 'weeklychartlist' ; end
|
130
|
+
class LastfmUserWeeklyChartListRequest < Base ; self.main_fieldname = 'weeklychartlist' ; self.response_type = 'weeklychartlist' ; end
|
131
|
+
class LastfmGroupWeeklyTrackChartRequest < Base ; self.main_fieldname = 'weeklytrackchart' ; self.response_type = 'weeklytrackchart' ; end
|
132
|
+
class LastfmUserWeeklyTrackChartRequest < Base ; self.main_fieldname = 'weeklytrackchart' ; self.response_type = 'weeklytrackchart' ; end
|
133
|
+
|
134
|
+
# class LastfmArtistImagesRequest < Base ; self.main_fieldname = 'images' ; end
|
135
|
+
# class LastfmUserPlaylistsRequest < Base ; self.main_fieldname = 'playlists' ; end
|
136
|
+
# class LastfmArtistPodcastRequest < Base ; self.main_fieldname = 'podcast' ; end
|
137
|
+
# class LastfmUserRecentStationsRequest < Base ; self.main_fieldname = 'recentstations' ; end
|
138
|
+
# class LastfmPlaylistfetchRequest < Base ; self.main_fieldname =''' ; end
|
139
|
+
# class LastfmTasteometercompareRequest < Base ; self.main_fieldname ='' ; end
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'wuclan/lastfm/scrape/base'
|
2
|
+
module Wuclan
|
3
|
+
module Lastfm
|
4
|
+
module Scrape
|
5
|
+
|
6
|
+
class LastfmRequestStream < Monkeyshines::RequestStream::KlassRequestStream
|
7
|
+
include Wuclan::Lastfm::Scrape
|
8
|
+
|
9
|
+
end
|
10
|
+
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
|
15
|
+
|
16
|
+
# if req.is_a?(LastfmArtistShoutsRequest) then p([req.parsed_contents["shouts"]["shout"].length, req.parsed_contents["shouts"]["@attr"]]) rescue nil
|
17
|
+
# end
|