2012-11-08 13 views
10

Ich kratze einige Websites mit BeautifulSoup und Anfragen. Es gibt eine Seite, die ich untersuche, die ihre Daten innerhalb eines Tags <script language="JavaScript" type="text/javascript"> hat. Es sieht wie folgt aus:Parsen von variablen Daten aus einem Javascript-Tag mit Python

<script language="JavaScript" type="text/javascript"> 
var page_data = { 
    "default_sku" : "SKU12345", 
    "get_together" : { 
     "imageLargeURL" : "http://null.null/pictures/large.jpg", 
     "URL" : "http://null.null/index.tmpl", 
     "name" : "Paints", 
     "description" : "Here is a description and it works pretty well", 
     "canFavorite" : 1, 
     "id" : 1234, 
     "type" : 2, 
     "category" : "faded", 
     "imageThumbnailURL" : "http://null.null/small9.jpg" 
     ...... 

Gibt es eine Möglichkeit, dass ich ein Python-Wörterbuch oder JSON-Objekt aus dem page_data Variable in diesem Script-Tag erstellen können? Das wäre viel schöner, als mit BeautifulSoup Werte zu erreichen.

Antwort

22

Wenn Sie BeautifulSoup verwenden, um die Inhalte des <script> Tag zu bekommen, die json module kann mit ein bisschen String Magie den Rest:

jsonValue = '{%s}' % (textValue.split('{', 1)[1].rsplit('}', 1)[0],) 
value = json.loads(jsonValue) 

Die .split() und .rsplit() Combo oben aufgespalten den Text auf der ersten { und auf dem letzten } im JavaScript-Textblock, der Ihre Objektdefinition sein sollte. Indem wir die geschweiften Klammern wieder zum Text hinzufügen, können wir sie an json.loads() übergeben und eine Python-Struktur daraus erhalten.

Demonstration:

>>> import json 
>>> textValue = ''' 
... var page_data = { 
... "default_sku" : "SKU12345", 
... "get_together" : { 
...  "imageLargeURL" : "http://null.null/pictures/large.jpg", 
...  "URL" : "http://null.null/index.tmpl", 
...  "name" : "Paints", 
...  "description" : "Here is a description and it works pretty well", 
...  "canFavorite" : 1, 
...  "id" : 1234, 
...  "type" : 2, 
...  "category" : "faded", 
...  "imageThumbnailURL" : "http://null.null/small9.jpg" 
... } 
... }; 
... ''' 
>>> jsonValue = '{%s}' % (textValue.split('{', 1)[1].rsplit('}', 1)[0],) 
>>> value = json.loads(jsonValue) 
>>> value 
{u'default_sku': u'SKU12345', u'get_together': {u'category': u'faded', u'canFavorite': 1, u'name': u'Paints', u'URL': u'http://null.null/index.tmpl', u'imageThumbnailURL': u'http://null.null/small9.jpg', u'imageLargeURL': u'http://null.null/pictures/large.jpg', u'type': 2, u'id': 1234, u'description': u'Here is a description and it works pretty well'}} 
>>> import pprint 
>>> pprint.pprint(value) 
{u'default_sku': u'SKU12345', 
 u'get_together': {u'URL': u'http://null.null/index.tmpl', 
                   u'canFavorite': 1, 
                   u'category': u'faded', 
                   u'description': u'Here is a description and it works pretty well', 
                   u'id': 1234, 
                   u'imageLargeURL': u'http://null.null/pictures/large.jpg', 
                   u'imageThumbnailURL': u'http://null.null/small9.jpg', 
                   u'name': u'Paints', 
                   u'type': 2}} 
+0

Das ist wirklich toll und macht Sinn. Vielen Dank für Ihre Hilfe. – ajt

+0

Ich würde gerne wissen, wie ich dies für eine Objektdeklaration, die keine Anführungszeichen verwendet, um die Schlüssel des Objekts, z. 'default_sku:" SKU12345 ", ...'. Es würde wahrscheinlich nur eine Regex ... – 2rs2ts

+0

@ 2rs2ts: Siehe [Problem mit HTML-Tags beim Scraping von Daten mit schönen Suppe] (http://StackOverflow.com/A/14122300) für eine vorherige Antwort, die in Anführungszeichen fügt mache etwas gültiges JSON. –