2013-02-22 6 views
7

Ich versuche, Daten von der Bing-Such-API abzurufen, und da die vorhandenen Bibliotheken auf alten, abgekündigten APIs basieren, würde ich mich selbst mit der request-Bibliothek versuchen. Dies scheint die gebräuchlichste Bibliothek dafür zu sein. Mein Code sieht aus wieAntwortcodierung mit dem Modul "request" von node.js

var SKEY   = "myKey...." , 
    ServiceRootURL = 'https://api.datamarket.azure.com/Bing/Search/v1/Composite'; 

function getBingData(query, top, skip, cb) { 
    var params = { 
     Sources: "'web'", 
     Query: "'"+query+"'", 
     '$format': "JSON", 
     '$top': top, '$skip': skip 
     }, 
     req = request.get(ServiceRootURL).auth(SKEY, SKEY, false).qs(params); 
    request(req, cb) 
} 

getBingData("bookline.hu", 50, 0, someCallbackWhichParsesTheBody) 

gibt Bing einige JSON und ich kann manchmal aber mit ihm arbeiten, wenn die Antwort Körper eine große Menge an nicht-ASCII-Zeichen enthält JSON.parse beklagt, dass der String ungültig ist. Ich habe versucht, zu einem ATOM-Inhaltstyp zu wechseln, aber es gab keinen Unterschied, das XML war ungültig. Das Überprüfen des Antwortkörpers, wie in dem Rückruf request() verfügbar ist, zeigt tatsächlich fehlerhaften Code an.

Also habe ich die gleiche Anfrage mit etwas Python-Code versucht, und das scheint die ganze Zeit gut zu funktionieren. Als Referenz:

r = requests.get(
     'https://api.datamarket.azure.com/Bing/Search/v1/Composite?Sources=%27web%27&Query=%27sexy%20cosplay%20girls%27&$format=json', 
     auth=HTTPBasicAuth(SKEY,SKEY)) 
stuffWithResponse(r.json()) 

Ich bin nicht in der Lage, das Problem mit kleineren Antworten zu reproduzieren und nicht in der Lage (zum Beispiel der Anzahl der Ergebnisse zu begrenzen) ein einzelnes Ergebnis zu identifizieren, die das Problem verursacht (durch den Offset verstärkt). Mein Eindruck ist, dass die Antwort in Chunks gelesen, irgendwie transcodiert und schlecht wieder zusammengesetzt wird, was bedeutet, dass die json/atom Daten ungültig werden, wenn ein Multibyte-Zeichen geteilt wird, was bei größeren Antworten passiert, aber nicht bei kleinen.

Da ich neu in Node bin, bin ich nicht sicher, ob es etwas gibt, was ich tun sollte (Einstellung der Kodierung irgendwo? Bing gibt UTF-8 zurück, so scheint dies nicht erforderlich).

Hat jemand eine Vorstellung von dem, was vor sich geht?

FWIW, ich bin auf OSX 10.8, Knoten ist v0.8.20 über MacPorts installiert, Anfrage ist v2.14.0 über npm installiert.

Antwort

1

Ich bin mir nicht sicher über die Anfrage-Bibliothek, aber die Standard-Nodejs funktioniert gut für mich. Es scheint auch viel einfacher zu lesen als Ihre Bibliothek und kommt tatsächlich in Stücke zurück.

http://nodejs.org/api/http.html#http_http_request_options_callback oder https (wie Ihre req) http://nodejs.org/api/https.html#https_https_request_options_callback (das gleiche wirklich though)

Für die Optionen ein kleiner Tipp: url Verwendung analysieren

var url = require('url'); 

var params = '{}' 

var dataURL = url.parse(ServiceRootURL); 
var post_options = { 
    hostname: dataURL.hostname, 
    port: dataURL.port || 80, 
    path: dataURL.path, 
    method: 'GET', 
    headers: { 
     'Content-Type': 'application/json; charset=utf-8', 
     'Content-Length': params.length 
    } 
}; 

offensichtlich params muss die Daten, die Sie sein möchte senden

+0

TBH, damit hatte ich versucht, es so zu tun (obwohl 'mit https.get' anstatt' .request') zu aber ich konnte es nicht zur Arbeit bringen, ich muss etwas falsch gemacht haben. Jedenfalls scheint es jetzt zu funktionieren, also werde ich Ihre Antwort trotzdem akzeptieren, wenn jemand keine Lösung für die Verwendung des Request-Moduls zur Verfügung stellt. Vielen Dank! – riffraff

+1

Möglicherweise hat es mehr damit zu tun, dass der JSON tatsächlich fehlerhaft ist. Wenn Sie eine Zeichenfolge mit einem Multibyte-Zeichen darin haben und die 'Content-Length' als' params.length' übergeben, dann sagen Sie, dass der Inhalt dieselbe Bytelänge hat wie die Anzahl der Zeichen in der Zeichenfolge. Dies gilt nicht für Multibyte-Zeichen. Anstelle von '{" name ":" feeé "}' erhält Ihre API wahrscheinlich '{" name ":" feeé "' – amsross

0

Ich denke, Ihre Anfrage Authentifizierung ist falsch. Die Authentifizierung muss vor request.get erfolgen. Siehe Dokumentation für request HTTP authentication. qs ist ein Objekt, das genau wie URL und Auth an request options übergeben werden muss. Auch Sie verwenden das gleiche req für die zweite Anfrage. Sie sollten wissen, dass request.get einen Stream für das angegebene GET von URL zurückgibt. Ihre nächste Anfrage mit req wird falsch gehen.

Wenn Sie nur HTTPBasicAuth benötigen, sollten diese auch

//remove req = request.get and subsequent request 
request.get('http://some.server.com/', { 
    'auth': { 
    'user': 'username', 
    'pass': 'password', 
    'sendImmediately': false 
    } 
},function (error, response, body) { 
}); 

Die Callback-Argument bekommt 3 Argumente arbeiten. Der erste ist ein Fehler, falls zutreffend (normalerweise von der http.Client-Option und nicht vom http.ClientRequest-Objekt). Die zweite ist ein http.ClientResponse-Objekt. Der dritte ist der Antworttext String oder Buffer. Das zweite Objekt ist der Antwortstream. Um es zu verwenden, müssen Sie die Ereignisse 'Daten', 'Ende', 'Fehler' und 'Schließen' verwenden.

Achten Sie darauf, die Argumente korrekt zu verwenden.

+0

nein, die fließende Syntax setzt die Optionen richtig, sie ist nur sehr schlecht dokumentiert. Mein Problem ist nicht Authentifizierung, ich kann sehen, dass es funktioniert und ich bekomme eine autorisierte Antwort. Mein Problem ist der verstümmelte Antworttext. – riffraff

0

Sie haben die Möglichkeit zu passieren {json: true} json Parsen der Antwort

+0

das Problem ist Codierung, nicht formatieren, wenn Sie die Frage gelesen habe ich auch mit ATOM versucht. Aber die Frage ist 18 Monate alt, also haben sie es hoffentlich behoben. – riffraff