2015-11-11 44 views
0

試圖收集學校項目的書價波動數據。我使用Python來從書籍回購聚合器(在本例中爲書籍路由器)中進行挖掘,但是我發現由於該網站必須加載數據,因此通過urllib2軟件包獲取源代碼爲我提供了源代碼數據被加載。數據加載完成後我該如何處理?網頁在加載其數據後正在抓取頁面

例子:http://bookscouter.com/prices.php?isbn=9788498383621&searchbutton=Sell

+0

答案總是美麗的。 – Erik

回答

0

您不能將此與Python只。您需要一個JavaScript引擎API,如PhantomJS

使用Phantom,將非常容易設置所有頁面內容的靜態和動態JavaScript內容(如Ajax調用結果)。逸岸你可以將網頁註冊事件處理程序到你的頁面分析器像(這是一個的node.js + phantom.js例子)

/* 
    * Register Page Handlers as functions 

    { 
     onLoadStarted : onLoadStarted, 
     onLoadFinished: onLoadFinished, 
     onError : onError, 
     onResourceRequested : onResourceRequested, 
     onResourceReceived : onResourceReceived, 
     onNavigationRequested : onNavigationRequested, 
     onResourceError : onResourceError 
    } 

    */ 
    registerHandlers : function(page, handlers) { 
     if(handlers.onLoadStarted) page.set('onLoadStarted',handlers.onLoadStarted) 
     if(handlers.onLoadFinished) page.set('onLoadFinished',handlers.onLoadFinished) 
     if(handlers.resourceError) page.set('onResourceError', handlers.resourceError) 
     if(handlers.onResourceRequested) page.set('onResourceRequested',handlers.onResourceRequested) 
     if(handlers.onResourceReceived) page.set('onResourceReceived',handlers.onResourceReceived) 
     if(handlers.onNavigationRequested) page.set('onNavigationRequested',handlers.onNavigationRequested) 
     if(handlers.onError) page.set('onError',handlers.onError) 

    } 

在這一點上,你有什麼事就完全控制,當在你的頁面必須下載,如:

var onResourceError = function(resourceError) { 
         var errorReason = resourceError.errorString; 
         var errorPageUrl = resourceError.url; 
       } 
       var onResourceRequested = function (request) { 
        var msg = ' request: ' + JSON.stringify(request, undefined, 4); 
       }; 
       var onResourceReceived = function(response) { 
        var msg = ' id: ' + response.id + ', stage: "' + response.stage + '", response: ' + JSON.stringify(response); 
       }; 
       var onNavigationRequested = function(url, type, willNavigate, main) { 
        var msg = ' destination_url: ' + url; 
        msg += ' type (cause): ' + type; 
        msg += ' will navigate: ' + willNavigate; 
        msg += ' from page\'s main frame: ' + main; 
       }; 
       page.onResourceRequested(
       function(requestData, request) { 
         //request.abort() 
         //request.changeUrl(url) 
         //request.setHeader(key,value) 
         var msg = ' request: ' + JSON.stringify(request, undefined, 4); 
         //console.log(msg) 
        }, 
       function(requestData) { 
         //console.log(requestData.url) 
       }) 
     PageHelper.registerHandlers(page, 
        { 
         onLoadStarted : onLoadStarted, 
         onLoadFinished: onLoadFinished, 
         onError : null, // onError THIS HANDLER CRASHES PHANTOM-NODE 
         onResourceRequested : null, // MUST BE ON PAGE OBJECT 
         onResourceReceived : onResourceReceived, 
         onNavigationRequested : onNavigationRequested, 
         onResourceError : onResourceError 
        }); 

正如你所看到的,您可以定義頁面處理程序,並採取流動的,因此加載該網頁上的資源的控制。所以,你可以肯定的是所有的數據準備和設置,你把整個頁面的源代碼像以前一樣:

var Parser = { 
    parse : function(page) { 

    var onSuccess = function (page) { // page loaded 
     var pageContents=page.evaluate(function() { 
      return document.body.innerText; 
     }); 
     } 
    var onError = function (page,elapsed) { // error 
    } 
    page.evaluate(function(func) { 
      return func(document); 
     }, function(dom) { 
      return true; 
     }); 

    } 
} // Parser 

在這裏,您可以看到的onSuccess回調加載整個頁面的內容:

var pageContents=page.evaluate(function() { 
       return document.body.innerText; 
      }); 

該頁面來自Phantomjs直接像下面的代碼片段:

phantom.create(function (ph) { 
      ph.createPage(function (page) { 
       Parser.parse(page) 
      }) 
     },options) 

當然,這給你和你可以用Node.js的+ Phantomjs,COMBIN時是超級強大做些什麼的想法編輯在一起。

您可以運行在Python ENV phantomjs,稱它像

try: 
      output = '' 
      for result in runProcess([self.runProcess, 
      self.runScript, 
      self.jobId, 
      self.protocol, 
      self.hostname, 
      self.queryString]): 
       output += '' + result 
       print output 
     except Exception as e: 
      print e 
      print(traceback.format_exc()) 

在您使用子POPEN執行二進制:

def runProcess(exe): 
    p = subprocess.Popen(exe, stdout=subprocess.PIPE, stderr=subprocess.STDOUT) 
    while(True): 
     retcode = p.poll() #returns None while subprocess is running 
     line = p.stdout.readline() 
     yield line 
     if(retcode is not None): 
     break 

過程中,進程運行的是的node.js在這種情況下,

self.runProcess='node' 

用你需要的參數作爲參數。

+0

雖然一個長而有趣的答案,這根本不回答提問者的問題。有些方法可以用Python來完成。 –

+0

我不建議你通過Python(我是一個經驗豐富的Python開發人員)。 Phantomjs(用C++編寫)是頂級公司使用的真實世界的JavaScript引擎。這是我的2美分(https://en.wikipedia.org/wiki/PhantomJS#Companies_using_PhantomJS)。然後你決定。我會建議使用另一個python web解析器,但不是,在我看來這不是最好的答案。 – loretoparisi

+0

看,我同意使用Python並不是最好的解決方案。但是問題是「我如何用Python做X?」,並且X *在Python中是可能的,所以不要只回答「不要,只是使用不同的語言」。 –

1

挑戰是讀取數據,一旦它被網絡瀏覽器渲染,這將需要一些額外的技巧。如果您可以看到該網站是否有預渲染版本*或API。

This article (linked from the Web archive)有一個很好的細分你需要做什麼。它可以概括然而由於:

  1. 選擇一個良好的Python-WebKit的渲染器(在文章PyQt的情況下)
  2. 使用窗口小部件來獲取和渲染頁面
  3. 取渲染HTML從小部件
  4. 使用像lXML或BeautifulSoup這樣的庫來解析這個HTML。

*小咆哮 - 不得不希望預渲染的版本的想法應該是一個靜態網頁激怒我。