root/trunk/plagger/lib/Plagger/Plugin/CustomFeed/YouTube.pm

Revision 1888 (checked in by mizzy, 14 years ago)

CustomFeed?::YouTube?: fix regexp to get page content

Line 
1 package Plagger::Plugin::CustomFeed::YouTube;
2 use strict;
3 use warnings;
4 use base qw( Plagger::Plugin );
5
6 use Plagger::Enclosure;
7 use Plagger::UserAgent;
8 use URI;
9 use Encode;
10
11 sub register {
12     my($self, $context) = @_;
13     $context->register_hook(
14         $self,
15         'subscription.load' => \&load,
16     );
17 }
18
19 sub load {
20     my($self, $context) = @_;
21     my $feed = Plagger::Feed->new;
22     $feed->aggregator(sub { $self->aggregate(@_) });
23     $context->subscription->add($feed);
24 }
25
26 sub aggregate {
27     my($self, $context, $args) = @_;
28
29     my $url  = URI->new('http://youtube.com/results');
30     my $file = $self->cache->path_to('youtube_search_result.html');
31     my $query = $self->conf->{query};
32
33     $query = encode('UTF-8', $query) unless $context->conf->{no_decode_utf8};
34
35     $context->log( info => 'Getting YouTube search results for ' . $query );
36
37     my $ua = Plagger::UserAgent->new;
38
39     my $feed = Plagger::Feed->new;
40     $feed->type('youtubesearch');
41     $feed->title("YouTube Search - $query");
42
43     my $page = $self->conf->{page} || 1;
44     my $sort = $self->conf->{sort} || 'video_date_uploaded';
45
46     for ( 1 .. $page ){
47         $url->query_form(
48             search_type     => 'search_videos',
49             search_query    => $query,
50             search_sort     => $sort,
51             search_category => 0,
52             page            => $_,
53         );
54
55         my $res = $ua->mirror( $url->as_string => $file );
56
57         if($res->is_error){
58             $context->log( error => $res->status );
59             return;
60         }
61
62         open my $fh, "<:encoding(utf-8)", $file
63             or return $context->log(error => "$file: $!");
64
65         my (@videos, $data, $title_flag, $tag_flag);
66         while (<$fh>) {
67             # get title
68             m!<div class="vtitle">!
69                 and $title_flag = 1;
70             m!<a href="/watch\?v=([^"]+)"[^>]+>(.+)</a>!
71                 and do {
72                     if($title_flag){
73                         $data->{title} = $2;
74                         $data->{id} = $1;
75                         $title_flag = 0;
76                     }
77                 };
78             # get image url
79             m!<img src="(http://[\w-]*static\d+(.[\w-]+)?\.youtube.com/[^">]+/[12].jpg)" border="0" class="vimg120" />!
80                 and $data->{image}->{url} = $1;
81             # get description
82             m!<div class="vdesc">!
83                 and do {
84                     <$fh>;
85                     $data->{description} = <$fh>;
86                 };
87             # get tags
88             m!<div class="vtagLabel">Tags:</div>!
89                 and $tag_flag = 1;
90             m!(<a href="/results\?search_query=.*)!
91                 and do {
92                     if($tag_flag){
93                         $data->{tags} = $1;
94                         $tag_flag = 0;
95                     }
96                 };
97             # get author
98             m!From:</span> <a href="/user/[^>]+">([^<]+)</a>!
99                 and $data->{author} = $1;
100             m/<!-- end vEntry -->/
101                 and do {
102                     $context->log( info => 'Got ' . $data->{title});
103                     my $entry = Plagger::Entry->new;
104                     $entry->title($data->{title});
105                     $entry->link('http://youtube.com/watch?v=' . $data->{id});
106                     $entry->icon({
107                         url    => $data->{image}->{url},
108                         #width  => $data->{image}->{width},
109                         #height => $data->{image}->{height},
110                     });
111                     $entry->summary($data->{description});
112                     $entry->body($data->{description});
113                     $entry->author($data->{author});
114
115                     # tags
116                     while( $data->{tags} =~ /<a href="\/results\?search_query=[^"]+" class="dg">([^<]+)<\/a>/gms){
117                         $entry->add_tag($1);
118                     }
119
120                     # enclosure
121                     my $video_url = $self->cache->get_callback(
122                         "item-" . $entry->link, sub {
123                             my $res = $ua->fetch($entry->link);
124                             if ($res->is_error){
125                                 $context->log( error => $res->status );
126                                 return;
127                             }
128                             my $url;
129                             if ($res->content =~ /&t=([^&]+)/gms){
130                                 $url = 'http://youtube.com/get_video?video_id=' . $data->{id} . "&t=$1";
131                             }
132                             return $url;
133                         },
134                         '24 hours',
135                     );
136
137                     if ($video_url) {
138                         warn $video_url;
139                         my $video_id = ( $video_url =~ /video_id=(\w+)/ )[0];
140
141                         my $enclosure = Plagger::Enclosure->new;
142                         $enclosure->url( URI->new($video_url) );
143                         $enclosure->type('video/x-flv');
144                         $enclosure->filename("$video_id.flv");
145                         $entry->add_enclosure($enclosure);
146                     }
147
148                     $feed->add_entry($entry);
149                     $data = {};
150             };
151         }
152     }
153
154     $context->update->add($feed);
155 }
156
157 1;
158 __END__
159
160 =head1 NAME
161
162 Plagger::Plugin::CustomFeed::YouTube - Get YouTube search result or rss
163
164 =head1 SYNOPSIS
165
166   - module: CustomFeed::YouTube
167     config:
168       query: Twenty Four
169       sort: video_date_uploaded
170       page: 5
171
172 =head1 DESCRIPTION
173
174 This plugin fetches the result of YouTube search or the rss of a specified tag.
175
176 =head1 CONFIG
177
178 =over 4
179
180 =item query
181
182 Specify search query.
183
184 =item sort
185
186 Set sort condition. Available conditions are below. Default is video_date_uploaded.
187
188   relevance
189   video_date_uploaded
190   video_view_count
191   video_avg_rating
192
193 =item page
194
195 Number of pages of search result you get. Default is 1.
196
197 =back
198
199 =head1 AUTHOR
200
201 Gosuke Miyashita
202
203 =head1 SEE ALSO
204
205 L<Plagger>
206
207 =cut
Note: See TracBrowser for help on using the browser.