2014-09-16 3 views
2

javascript로 채워진 페이지를 긁어 내려고합니다. URL은 : 나는 데이터를 얻기 위해 다음 코드를 사용했다Python을 사용하여 웹 페이지의 스크립트를 실행하십시오.

http://www.nasdaqomxnordic.com/index/index_info?Instrument=DK0016268840

. 분명히이 코드는 자바 스크립트를 처리하고 완전한 HTML 파일을 반환해야하지만 그렇지 않습니다. 타이밍 문제가있을 수 있습니다. 그렇다면 전체 HTML을 허용하기 위해 어디에서 proram을 지연 시킬지 명확하지 않습니다.

import sys 
from PyQt4.QtGui import * 
from PyQt4.QtCore import * 
from PyQt4.QtWebKit import * 

class Render(QWebPage): 
    def __init__(self, url): 
     self.app = QApplication(sys.argv) 
     QWebPage.__init__(self) 
     self.loadFinished.connect(self._loadFinished) 
     self.mainFrame().load(QUrl(url)) 
     self.app.exec_() 

    def _loadFinished(self, result): 
     self.frame = self.mainFrame() 
     self.app.quit() 

def getHtml(str_url): 
    r_html = Render(str_url) 
    html = r_html.frame.toHtml() 
    return html 

str_url = 'http://www.nasdaqomxnordic.com/index/index_info?Instrument=DK0016268840' 
str_html = getHtml(str_url) 
print(str_html) 

이렇게하면 웹 브라우저에서 페이지 소스를 요청하면 얻을 수있는 html이 제공됩니다. 물론 모든 테이블이 자바 스크립트 함수로 채워지는 것처럼 페이지에 더 많은 것들이 있습니다. Firebug를 사용하면 내가 찾고있는 테이블의 id는 "sharesInIndexTable"입니다. 정말로 긁고 싶은 항목은 각 회사의 이름 아래에있는 링크입니다.하지만 beautifulsoup를 구문 분석하기 위해 전체 테이블에 액세스하는 것이 더 좋을 것입니다. 이 테이블에서 "Carlsberg"라는 단어를 찾을 수 있어야합니다 (AJAX가 완전히로드되었는지 확인하기위한 잠재적 인 테스트로서). DOM을 구문 분석 할 항목을 찾으려고 시도하고 다음을 시도했습니다.

import sys 
from PyQt4 import QtGui, QtCore, QtWebKit 

class Sp(): 
    def printit(self):   
     data = self.webView.page().mainFrame().findFirstElement('id="sharesInIndexTable"') 
    print(data)  

def main(self): 
    self.webView = QtWebKit.QWebView() 
    self.webView.load(QtCore.QUrl("http://www.nasdaqomxnordic.com/index/index_info?Instrument=DK0016268840")) 
    QtCore.QObject.connect(self.webView,QtCore.SIGNAL("loadFinished(bool)"),self.printit) 

    app = QtGui.QApplication(sys.argv) 
    s = Sp() 
    s.main() 
    sys.exit(app.exec_()) 

이 코드는 또한 PyQt4.QtWebkit.QWebElement 객체가 0x03294830 (결과가 다를 수 있음)입니다.이 주소를 읽을 수있는 형식으로 만들려고 했는데도 실패했습니다.이 코드는 두 번 실행되는 것 같습니다. 그런 다음이 중 하나를 시도했습니다. (약간 필요에 맞게 조정) :

#!/usr/bin/python 

# These lines will get us the modules we need. 
from PyQt4.QtCore import QUrl, SIGNAL 
from PyQt4.QtGui import QApplication 
from PyQt4.QtWebKit import QWebPage, QWebView 

class Scrape(QApplication): 
    def __init__(self): 
    # only work with ["test"] as it normally takes an array of args 
    super(Scrape, self).__init__(["test"]) 
    # Create a QWebView instance and store it. 
    self.webView = QWebView() 
    # Connect our searchform method to the searchform signal of this new 
    # QWebView. 
    self.webView.loadFinished.connect(self.searchForm) 

    def load(self, url): 
    # In the __init__ we stored a QWebView instance into self.webView so 
    # we can load a url into it. It needs a QUrl instance though. 
    self.webView.load(QUrl(url)) 

    def searchForm(self): 
    # We landed here because the load is finished. Now, load the root document 
    # element. It'll be a QWebElement instance. QWebElement is a QT4.6 
    # addition and it allows easier DOM interaction. 
    documentElement = self.webView.page().currentFrame().documentElement() 
    # Let's find the search input element. 
    print("Begin search") 
    inputSearch = documentElement.findFirst('id="sharesInIndexTable"') 
    # Disconnect ourselves from the signal. 
    self.webView.loadFinished.disconnect(self.searchForm) 
    print("End search") 
    # And connect the next function. 
    self.webView.loadFinished.connect(self.searchResults) 

    def searchResults(self): 
    # As seen above, first grab the root document element and then load all g 
    # classed list items. 
    print("Begin results") 
    results = self.webView.page().currentFrame().documentElement().findAll('td') 

    # Change the resulting QWebElementCollection into a list so we can easily 
    # iterate over it. 
    for e in results.toList(): 
    # Just print the results. 
    print(e.tohtml()) 
    # We are inside a QT application and need to terminate that properly. 
    print("End results") 
    self.exit() 

# Instantiate our class. 
my_scrape = Scrape() 
# Load the Google homepage. 
my_scrape.load('http://www.nasdaqomxnordic.com/index/index_info?Instrument=DK0016268840') 
# Start the QT event loop. 
my_scrape.exec_() 

프로그램이 명령을 완전히 실행하고 있는지 확인하기 위해 print() 문을 추가했습니다. 내가 "execute_script"명령이 알고

var sharesInIndex = { 
load: function() { 
var index = webCore.getInstrument(); 
var nLabel = 'nm'; 
var hiddenAttributes = ",lists,tp,hlp,isin,note,"; 
var xslt = "inst_table.xsl"; 
var options = ",noflag,sectoridicon,"; 
var xpath = "//index//instruments"; 
// Check if swedish r�nteindex or Icelandic r�nteindex. 
if (index.indexOf('OMFSE') >= 0 || webCore.getInstrument().indexOf('IS00000') >= 0) { 
    hiddenAttributes += ",to,sectid,"; 
    nLabel = 'fnm'; 
} 

// Check if weights index present (typeof) 
var shbindex = ",SE0002834820,SE0002834838,SE0002834846,SE0002977397,"; 
if (shbindex.indexOf(index) >= 0) { 
    xslt = "inst_table_windex.xsl"; 
    options += "windex,"; 
    xpath = "//index"; 
} 

var query = webCore.createQuery(
    Utils.Constants.marketAction.getIndexInstrument, { 
    inst__a: "0,1,2,5,37,4,20,21,23,24,33,34,97,129,98,10", /* 87,*/ 
    Instrument: index, 
    XPath: xpath, 
    ext_xslt: xslt, 
    ext_xslt_lang: currentLanguage, 
    ext_xslt_tableId: "sharesInIndexTable", 
    ext_xslt_hiddenattrs: hiddenAttributes, 
    ext_xslt_notlabel: nLabel, 
    ext_xslt_options: options 
    }); 

    $("#sharesInIndexOutput").empty().loading("/static/nordic/css/img/loading.gif"); 
    $("#sharesInIndexOutput").load(webCore.getProxyURL('prod'), {xmlquery: query}, 
    function(responseText, textStatus, XMLHttpRequest) { 
     $("#sharesInIndexTable").tablesorter({ 
     widgets: ['zebra'], 
     textExtraction: 'complex', 
     numberFormat: Utils.Constants.numberFormat[currentLanguage] 
     }); 
     $("#sharesInIndexTable a").each(function() { 
     $(this).attr("href",webCore.getURL(Utils.Constants.pages.micrositeShare, $(this).attr('name'))); 
     }); 
    }); 
    } 
}; 

$(document).ready(sharesInIndex.load); 

하지만 I : 소스 페이지를 검사 (인쇄 문 제외) 모두에서이 생산 아무것도

, 나는 테이블 그것이 채울 스크립트를 찾을 수 있습니다 요법을 구현하는 방법을 모르거나이 예제에 적합한 예제를 찾지 못했습니다. 결과가 Json인지 또는 HTML인지 또는 일반 텍스트인지는 상관 없습니다. 나는 이것이 답이있는 곳이라고 믿는다. (1) 페이지를로드한다. (2) 페이지를 위해 스크립트를 실행한다. (3) 결과를 얻는다. (4) 결과를 파싱/프린트/저장한다. ...

하나 있다면 헤드리스 솔루션을 가지고 있고 Windows의 Phantomjs도 cmd 창을 튀어 나오기 때문에 완전히 헤드리스가되지는 않습니다. (리눅스에서 가상 디스플레이로이를 제거 할 수 있다는 것을 알고 있습니다.하지만 그렇지 않습니다. 환경). 또한, 저에게 말하길 : 데이터를로드했는지 확인하기 위해 폴을 폴링해야합니다. 그러면 검색하는 것이 도움이되지 않습니다. 설문 조사 방법과 더 중요한 것은 대략 어디에서 의사 코드로 말할 수 있습니까? 프로그램은 폴링이 발생한다는 것을 의미합니다 (즉, 완전한 실행 코드를 게시 한 이유 - 다른 사람이 동일한 문제를 가지고 있으면 완전하고 이해하기 쉬운 대답을해야 함).

내 최신 시도한다 (- 1 AJAX로드 할 수 있도록 지연을 삽입)

import sys 
from PyQt4.QtGui import * 
from PyQt4.QtCore import * 
from PyQt4.QtWebKit import * 
import time 

class Render(QWebPage): 
    def __init__(self, url): 
    self.app = QApplication(sys.argv) 
    QWebPage.__init__(self) 
    self.mainFrame().load(QUrl(url)) 
    self.loadFinished.connect(self._loadFinished) 
    self.app.exec_() 

    def _loadFinished(self, result): 
    time.sleep(5) 
    self.frame = self.currentFrame() 
    self.app.quit() 

url = 'http://www.nasdaqomxnordic.com/index/index_info?Instrument=DK0016268840' 
r = Render(url) 
html = r.frame.toHtml() 
print(html) 

(2 - 소스 페이지에서 알려진 항목에 대한 폴링) - 방화 관리자 발견 항목 - 어쩌면 구문 findFirst의 인수가 잘못되었습니다.

import sys 
from PyQt4.QtGui import * 
from PyQt4.QtCore import * 
from PyQt4.QtWebKit import * 
import time 

class Render(QWebPage): 
    def __init__(self, url): 
    self.app = QApplication(sys.argv) 
    QWebPage.__init__(self) 
    self.mainFrame().load(QUrl(url)) 
    self.loadFinished.connect(self._loadFinished) 
    self.app.exec_() 

    def _loadFinished(self, result): 
    counter = 0 
    while(self.mainFrame().documentElement().findFirst("id=sharesInIndexTable")): 
     counter+=1 
     print(counter) 
     time.sleep(1)  
    self.frame = self.currentFrame() 
    self.app.quit() 

url = 'http://www.nasdaqomxnordic.com/index/index_info?Instrument=DK0016268840' 
r = Render(url) 
html = r.frame.toHtml() 
print(html) 

마지막 항목에 문제가 발생했음을 나타내는 카운터가 있습니다. 그것은 영원히 중요하며 ctrl-c를 사용하여 중지해야합니다.

(3 - 또 다른 변형 사용 WebElement)

import sys 
from PyQt4.QtGui import * 
from PyQt4.QtCore import * 
from PyQt4.QtWebKit import * 
import time 

class Render(QWebPage): 
    def __init__(self, url): 
    self.app = QApplication(sys.argv) 
    QWebPage.__init__(self) 
    self.mainFrame().load(QUrl(url)) 
    self.loadFinished.connect(self._loadFinished) 
    self.app.exec_() 

    def _loadFinished(self, result): 
    table = self.mainFrame().documentElement().findFirst("id=sharesInIndexTable") 
    print(table) #prints: <PyQt4.QtWebKit.QWebElement object at 0x0319FB0> 
    print("Attributes:") 
    print(table.attributeNames()) #prints: [] i.e. None 
    print("Classes: ") 
    print(table.classes())  #prints: [] i.e. None 
    print("InnerXML: " + table.toInnerXml()) #prints nothing 
    print("OuterXML: " + table.toOuterXml()) #prints nothing 
    print("Done") 
    self.frame = self.currentFrame() 
    self.app.quit() 

url = 'http://www.nasdaqomxnordic.com/index/index_info?Instrument=DK0016268840' 
r = Render(url) 
html = r.frame.toHtml() 

이 하나 없음 성공 중 하나. 나는 인쇄 된 것을 코드에 넣었다. 거기에는 분명히 물체가 있지만 내부에 무엇이 있는지 나는 볼 수 없습니다.

답변

1

가 나는 그것이 오랜 시간이 지났 알고 있지만,이 대답은 비슷한 상황

나는 비슷한 문제를 타격 한 이후에 방문자와 나는 같은 QWebPage뿐만 아니라 QWebFrame에서 loadFinished에서 신호 대기 등 다양한 일을 시도, 등 QWebFrame.intialLayoutCompleted()

결국 나를 위해 일한 것은에서 신호를 기다리는 것은 이것이다 :

난 그냥 보통의 브라우저에서 페이지를 렌더링합니다. javascript로 인해 PyQt에서 렌더링되지 않은 요소를 검사하고 해당 요소의 ID를 얻습니다 (여러 요소, 테이블 등이 포함 된 div 인 경우 div id를 얻음). 이제 yourPage.loadFinished 함수의 python 코드에서 yourFrame.evaluateJavaScript ("document.getElementById (element_id_retrieved_earlier ')")를 호출하십시오.

그러면 ID가 검색 될 때까지 기다리고 내재 된 스크립트가 실행될 때까지 기다립니다.

+0

https://euronext.com/en/products/equities/NL0000352565-XAMS/market-information 및 elementID = 'instrument-factsheet'를 사용하여 솔루션을 구현하려했지만이 작업을 수행하면 안됩니다. 방법의 일부 코드 스 니펫을 게시하시기 바랍니다. 감사. – Eric

관련 문제