2014-02-10 7 views
0

Мне нужно получить json, который инкрустирован внутри тега скрипта на определенной странице ... поэтому я не могу использовать обычные методы очистки, такие как cheerio. Простой выход, напишите файл (загрузите страницу) на сервер, а затем прочитайте его, используя строковые манипуляции, чтобы извлечь json (есть несколько), работать над ними и быстро сэкономить на моем db.Как писать и сразу читать файл nodeJS

Дело в том, что я слишком новичок в nodeJS и не могу заставить код работать, я думаю, что я пытаюсь прочитать файл, прежде чем он будет полностью написан, и если вы прочитаете его до получения [Объект Object] ...

Вот что я до сих пор ...

var http = require('http'); 

var fs = require('fs'); 
var request = require('request'); 

var localFile = 'tmp/scraped_site_.html'; 
var url = "siteToBeScraped.com/?searchTerm=foobar" 

// writing 
var file = fs.createWriteStream(localFile); 

var request = http.get(url, function(response) { 
    response.pipe(file); 
}); 

//reading 
var readedInfo = fs.readFileSync(localFile, function (err, content) { 
    callback(url, localFile); 
    console.log("READING: " + localFile); 
    console.log(err); 
}); 
+0

Не хватает времени, чтобы предоставить официальный и проверенный ответ, но вы правы. послушайте file.on ('finished', function() {}), см. http://nodejs.org/api/stream.html#stream_event_finish –

ответ

0

Согласно http module помощи «получить» не возвращает тело ответа

Это модифицированное из пример запроса на той же странице

Что вам нужно сделать, это процесс с ответом на обратном вызов (функции) передается в http.request так можно назвать, когда он готов к работе (асинхронный)

var http = require('http') 
var fs = require('fs') 

var localFile = 'tmp/scraped_site_.html' 
var file = fs.createWriteStream(localFile) 

var req = http.request('http://www.google.com.au', function(res) { 
    res.pipe(file) 
    res.on('end', function(){ 
    file.end() 

    fs.readFile(localFile, function(err, buf){ 
     console.log(buf.toString()) 
    }) 

    }) 
}) 

req.on('error', function(e) { 
    console.log('problem with request: ' + e.message) 
}) 

req.end(); 

EDIT Я обновил пример для чтения файла после его создания. Это работает путем обратного вызова в конце события ответа, который закрывает трубу, а затем он может снова открыть файл для чтения. В качестве альтернативы вы можете использовать

req.on('data', function(chunk){...}) 

обрабатывать данные по мере их поступления, не поставив его во временный файл

1

Поэтому в первую очередь я думаю, вы должны понять, что пошло не так.

Операция http-запроса является асинхронной. Это означает, что код обратного вызова в http.get() будет запущен в будущем, но fs.readFileSync из-за его синхронного характера будет выполняться и завершаться даже до того, как HTTP-запрос будет фактически отправлен в фоновый поток, который будет выполняться он, так как они оба вызываются в том, что обычно называют типом. Также fs.readFileSync возвращает значение и не использует обратный вызов.

Даже если вы замените fs.readFileSync на fs.readFile, код будет работать некорректно, поскольку операция readFile может выполняться до того, как ответ HTTP полностью будет считываться из сокета и записываться на диск.

я настоятельно рекомендую прочитать: stackoverflow question и/или Understanding the node.js event loop

Правильное место для вызова файла прочитанных когда поток ответа имеет закончил запись в файл, который будет выглядеть примерно так:

var request = http.get(url, function(response) { 
    response.pipe(file); 
    file.once('finish', function() {    
     fs.readFile(localFile, /* fill encoding here */, function(err, data) { 
      // do something with the data if there is no error 
     });   
    }); 
}); 

Конечно, это очень сырой и не рекомендуется писать асинхронный код, но это совсем другое обсуждение.

Сказав это, если вы загрузите файл, напишите его на диск и затем снова прочитайте все его содержимое в памяти для манипуляции, вы также можете отказаться от части файла и сразу же прочитать ответ в строке ,Ваш код будет выглядеть примерно так (это может быть реализовано несколькими способами):

var request = http.get(url, function(response) { 
    var data = ''; 

    function read() {  
     var chunk; 
     while (chunk = response.read()) { 
      data += chunk;  
     }  
    } 

    response.on('readable', read); 

    response.on('end', function() { 
     console.log('[%s]', data); 
    }); 
}); 

Что вы действительно должны сделать ММО, чтобы создать поток, который будет стирают все данные, необходимые от ответа преобразования, в то время как не потребляют слишком много памяти и плодоношения это более элегантно глядя код:

var request = http.get(url, function(response) { 
    response.pipe(yourTransformStream).pipe(file) 
}); 

Реализация этого преобразования потока, однако, может оказаться немного более сложным. Поэтому, если вы новичок на уровне узлов, и вы не планируете загружать большие файлы или много мелких файлов, чем, может быть, загружать все это в память, а выполнение строковых манипуляций на нем может быть проще.

Для получения дополнительной информации о преобразовании потоков:

Наконец, увидеть, если вы можете использовать любой из миллиона узлов .js, которые уже там :-) взгляните на these search results на np m

+0

Спасибо, что я провел последние 2 дня, читая то, что вы указали мне, и думаю, что я пойду неправильно здесь ... – Marcos

0

Мое впечатление, что вы сериализуете объект js в JSON, читая его из потока, который загружает файл, содержащий HTML. Это нелегко, но сложно. Его трудно узнать, когда вы находите выражение поиска, потому что, если вы анализируете, как куски входят, вы никогда не знаете, получили ли вы только контекст, и вы никогда не сможете найти то, что ищете, потому что оно было разделено на две или несколько частей которые никогда не анализировались в целом.

Вы могли бы попробовать что-то вроде этого:.

http.request('u/r/l',function(res){ 
    res.on('data',function(data){ 
     //parse data as it comes in 
    } 
}); 

Это позволяет считывать данные, как это происходит в Вы можете справиться с этим, чтобы сохранить на диск, дБ, или даже разобрать его, если накопленное содержимое в теги сценария в одну строку, затем анализируют объекты в этом.

Смежные вопросы