Skip to content
This repository

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse code

Oprava parsování stopáže a plakátů

! opraveno načítání URL plakátů (hlavní plakáte načítal dvakrát)
! opraveno parsování stopáže (nepočítalo s alternativní stopáží)
+ přidána vlastnost runtime_str obsahující celý řetězec stopáže jako text
* doplnění/úprava dokumentace
  • Loading branch information...
commit 3fc4ecd120d4aeb7c9db60127d6697756cc6ec6e 1 parent 50300fd
Jakub Jirutka authored

Showing 2 changed files with 58 additions and 27 deletions. Show diff stats Hide diff stats

  1. 7  README.md
  2. 78  csfd.py
7  README.md
Source Rendered
@@ -5,16 +5,17 @@ Parser pro stránky filmů a vyhledávání na [ČSFD](http://www.csfd.cz) napsa
5 5
 
6 6
 ## Poznámky
7 7
 
8  
-ČSFD je nejznámější Česko-Slovenská filmová databáze. Obsahuje informace o více než čtvrt milionech českých a zahraničních filmech, dále informace o hercích, režisérech atd. Bohužel ale neposkytuje žádné API pro strojový přístup k datům, žádné webové služby. Jediný způsob, jaký z ní dostat data, je parsováním webových stránek. A přesně k tomu vznikl tento kód.
  8
+[ČSFD](http://www.csfd.cz) je nejznámější Česko-Slovenská filmová databáze. Obsahuje informace o více než čtvrt milionu českých a zahraničních filmů, dále informace o hercích, režisérech atd. Bohužel ale neposkytuje žádné veřejné API pro strojový přístup k datům, žádné webové služby. Jediný způsob, jakým z ní dostat data, je parsováním webových stránek. A přesně k tomu vznikl tento kód.
9 9
 
10  
-Webové stránky ČSFD mají sice _doctype_ XHTML+RDFa, ale přitom jsem v nich žádné RDFa značky nenašel a dokonce nejsou ani _well-formed_. Všechny parsery, které jsem pro ČSFD našel (a jeden z nich jsem kdysi sám napsal), stránky parsují sadou složitých regulérních výrazů. Jejich vymýšlení sice může být poměrně zábavné procvičení mozkových závitů na dlouhé zimní večery, ale následné udržování a upravování při změně designu stránek je nesmírně náročné. Navíc takové řešení není příliš rychlé. Chtěl jsem proto zkusit trochu jiný přístup.
  10
+Webové stránky ČSFD mají sice doctype XHTML+RDFa, ale přitom jsem v nich žádné RDFa značky nenašel a dokonce nejsou ani _well-formed_. Nelze je proto přímo zpracovat jako XML. Všechny parsery, které jsem pro ČSFD našel (a jeden z nich jsem kdysi sám napsal), stránky parsují sadou složitých regulérních výrazů. Jejich vymýšlení sice může být poměrně zábavné procvičení mozkových závitů na dlouhé zimní večery, ale následné udržování a upravování při změně designu stránek je nesmírně náročné. Navíc takové řešení není příliš rychlé. Chtěl jsem proto zkusit trochu jiný přístup.
11 11
 
12 12
 Tento parser není postavený na regulérních výrazech, ale místo toho využívá [HTML parser](http://lxml.de/), který ze stránky postaví XML DOM, nad kterým se poté dotazuje přes XPath. Lokalizace požadovaných elementů na stránce je díky XPath neuvěřitelně snadná a výsledný kód je krásně přehledný. Můžete sami porovnat například s [tímto](http://www.phpclasses.org/browse/file/33086.html) kódem.
13 13
 
14 14
 
15 15
 ## Požadavky
16 16
 
17  
-Vyžaduje Python 3 nebo novější a knihovnu [lxml](http://lxml.de/).
  17
+* Python 3 (testováno na 3.1)
  18
+* [lxml](http://lxml.de/) (testováno na 2.3.1)
18 19
 
19 20
 
20 21
 ## Upozornění
78  csfd.py
... ...
@@ -1,4 +1,3 @@
1  
-#!/usr/bin/python3
2 1
 # -*- coding: utf-8 -*-
3 2
 # encoding: utf-8
4 3
 
@@ -27,10 +26,15 @@
27 26
 #
28 27
 # Upozornění: Používejte tento kód pouze pro vlastní potřebu, nezneužívejte ho 
29 28
 # pro vykrádání databáze ČSFD!
  29
+#
  30
+# Požadavky: 
  31
+#   - Python 3 (testováno na verzi 3.1)
  32
+#   - lxml (testováno na verzi 2.3.1)
30 33
 # 
  34
+#
31 35
 # @author Jakub Jirutka <jakub@jirutka.cz>
32  
-# @version 1.0 beta
33  
-# @date 2011-12-15
  36
+# @version 1.0.1 beta
  37
+# @date 2011-12-16
34 38
 #
35 39
 
36 40
 from urllib.request import Request, urlopen
@@ -101,6 +105,9 @@ class Movie:
101 105
 
102 106
 
103 107
     def __init__(self, url):
  108
+        """
  109
+        - url: celá URL stránky filmu [string]
  110
+        """
104 111
         self.actors = list()
105 112
         self.best_rank = None
106 113
         self.content = None
@@ -114,7 +121,8 @@ def __init__(self, url):
114 121
         self.names = {}
115 122
         self.posters = list()
116 123
         self.rating = None
117  
-        self.runtime = None
  124
+        self.runtime_str = None
  125
+        self.url = url
118 126
         self.website_url = None
119 127
         self.worst_rank = None
120 128
         self.year = None
@@ -151,13 +159,13 @@ def _fetch_data(self, url):
151 159
             raw_cyr = profile.xpath("p[@class='origin']/text()")[0]
152 160
             cyr = list( i.strip() for i in raw_cyr.split(',') )
153 161
 
154  
-            # stopáž
155  
-            if (cyr[-1].endswith("min")):
156  
-                self.runtime = cyr.pop().rstrip(' min')
  162
+            # stopáž (celý řetězec; může obsahovat i stopáž režisérského střihu apod.)
  163
+            if ("min" in cyr[-1]):
  164
+                self.runtime_str = cyr.pop()
157 165
     
158 166
             # rok
159 167
             if (cyr[-1].isdigit()):
160  
-                self.year = cyr.pop()
  168
+                self.year = int( cyr.pop() )
161 169
 
162 170
             # země
163 171
             self.countries = [i for i in cyr]
@@ -190,50 +198,52 @@ def _fetch_data(self, url):
190 198
         # hodnocení
191 199
         try:
192 200
             rating = doc_rating.xpath("h2/text()")[0].strip('%')
193  
-            self.rating = int(rating)
  201
+            self.rating = int( rating )
194 202
         except IndexError: pass
195 203
 
196 204
         # umístění v žebříčku nejlepších
197 205
         try:
198 206
             rank = doc_rating.xpath("//a[contains(@href, 'nejlepsi')]/text()")[0]
199  
-            self.best_rank = int(rank.split('.')[0])
  207
+            self.best_rank = int( rank.split('.')[0] )
200 208
         except IndexError: pass
201 209
 
202 210
         # umíštění v žebříčku nejhorších
203 211
         try:
204 212
             rank = doc_rating.xpath("//a[contains(@href, 'nejhorsi')]/text()")[0]
205  
-            self.worst_rank = int(rank.rsplit('.')[0])
  213
+            self.worst_rank = int( rank.rsplit('.')[0] )
206 214
         except IndexError: pass
207 215
 
208 216
         # umístění v žebříčku nejoblíbenějších
209 217
         try:
210 218
             rank = doc_rating.xpath("//a[contains(@href, 'nejoblibenejsi')]/text()")[0]
211  
-            self.favorite_rank = int(rank.split('.')[0])
  219
+            self.favorite_rank = int( rank.split('.')[0] )
212 220
         except IndexError: pass
213 221
 
214 222
         # umístění v žebříčku nejrozporuplnějších
215 223
         try:
216 224
             rank = doc_rating.xpath("//a[contains(@href, 'nejrozporuplnejsi')]/text()")[0]
217  
-            self.controversial_rank = int(rank.split('.')[0])
  225
+            self.controversial_rank = int( rank.split('.')[0] )
218 226
         except IndexError: pass
219 227
 
220  
-        # main poster
221  
-        try:
222  
-            self.posters.append(doc.xpath("//div[@id='poster']/img/@src")[0])
223  
-        except IndexError: pass
224  
-
225  
-        # all posters
  228
+        # všechny plakáty (vč. hlavního)
226 229
         regexp = re.compile("url\('(.*)'")
227 230
         for raw in doc.xpath("//div[@id='posters']/div[2]//div/@style"):
228 231
             link = regexp.search(raw).group(1).replace('\\', '')
229 232
             self.posters.append(link)
230 233
 
231  
-        # Link to IMDb.com
  234
+        # pokud je k dispozici jen jeden plakát, tak se negeneruje sekce "posters",
  235
+        # takže musí načíst ze sekce "poster"
  236
+        if (len(self.posters) == 0):
  237
+            try:
  238
+                self.posters.append(doc.xpath("//div[@id='poster']/img/@src")[0])
  239
+            except IndexError: pass
  240
+
  241
+        # odkaz na IMDb.com
232 242
         try: 
233 243
             self.imbd_url = doc.xpath("//div[@id='share']//a[@title='profil na IMDb.com']/@href")[0]
234 244
         except IndexError: pass
235 245
 
236  
-        # Link to official website
  246
+        # odkaz na oficiální web filmu
237 247
         try:
238 248
             self.website_url = doc.xpath("//div[@id='share']//a[@class='www']/@href")[0]
239 249
         except IndexError: pass
@@ -267,9 +277,9 @@ def origo_lang(self):
267 277
         - return: jazyk původního název filmu [string]
268 278
         """
269 279
 
270  
-        langs = set(self.names.keys())
  280
+        langs = set( self.names.keys() )
271 281
 
272  
-        if (self.countries.count('Česko') or self.countries.count('Československo')):
  282
+        if (self.countries.count("Česko") or self.countries.count("Československo")):
273 283
             return 'cs'
274 284
 
275 285
         else:
@@ -297,10 +307,20 @@ def origo_name(self):
297 307
 
298 308
         - return: původní název filmu [string]
299 309
         """
300  
-
301 310
         return self.names[self.origo_lang]
302 311
 
303 312
 
  313
+    @property
  314
+    def runtime(self):
  315
+        """
  316
+        Vrátí standardní stopáž filmu jako číslo (ořízne případnou další
  317
+        stopáž uvedenou v závorce).
  318
+        
  319
+        - return: stopáž filmu [int]
  320
+        """
  321
+        return int( self.runtime_str.split()[0] ) if self.runtime_str else None
  322
+
  323
+
304 324
 
305 325
 class MovieSearchResult:
306 326
     """
@@ -310,6 +330,12 @@ class MovieSearchResult:
310 330
     """
311 331
 
312 332
     def __init__(self, name, name_alt, year, url):
  333
+        """
  334
+        - name: český název [string]
  335
+        - name_alt: druhý název (většinou původní název filmu) [string]
  336
+        - year: rok vydání [int]
  337
+        - url: celá URL stránky filmu [string]
  338
+        """
313 339
         self.name = name
314 340
         self.name_alt = name_alt
315 341
         self.url = url
@@ -334,6 +360,10 @@ class Person:
334 360
     """
335 361
     
336 362
     def __init__(self, name, profile_url):
  363
+        """
  364
+        - name: celé jméno [string]
  365
+        - profile_url: celá URL stránky profilu [string]
  366
+        """
337 367
         self.name = name
338 368
         self.profile_url = profile_url
339 369
 

0 notes on commit 3fc4ecd

Please sign in to comment.
Something went wrong with that request. Please try again.