下载"伪装"使用PyQT scraper

时间:2015-11-05 16:32:41

标签: python jsf download web-scraping pyqt

你好。

我很难使用PyQT抓取网站。问题是,该网站使用JSF,并且URL对于此中的所有内容都是相同的。让我们使用" http://somesi.te/searchData.jsf"在这个例子中。

我打开它,填写表单(目标是相同的URL),提交,并在同一页面中获取结果。直到我的脚本工作正常。

但结果返回1000个分页页面,底部有一个锚标记,用于将所有结果下载到一个文件中的Excel文件。 这个锚是#targeted,onClick事件调用MoJarra函数,jsfcljs:

<a href="#" onclick="mojarra.jsfcljs(document.getElementById('formX'),{'formX:j_idt999':'formX:j_idt999'},'');return false">

分析该功能,它只是在表单中附加<input type="hidden">,然后再次提交,大概是服务器理解它并向我发送Excel文件而不是网页。

问题是:服务器返回文件&#34;伪装&#34;作为网页。 URL仍然是&#34; somesi.te / searchData.jsf&#34;,并且由于标题,浏览器将其识别为文件。

当我尝试使用unsupportedContent()来获取文件时,似乎它不会跟随流,它只是尝试获取在unsupportedContent信号中收到的URL。作为当前的URL&#34; somesi.te / searchData.jsf&#34;,当我保存文件时,我得到了页面的源代码,而不是获取我的文件。

以下是我现在使用的代码:

def getTicketDetails(self):
    self.webView.loadFinished.disconnect(self.getTicketDetails)

    self.webView.page().setForwardUnsupportedContent(True)
    self.webView.page().unsupportedContent.connect(self.downloadExcel)

    downloadButton = documentElement.findFirst('input[id="force_download"]')
    downloadButton.evaluateJavaScript("this.click();")    

def downloadExcel(self, reply):
    self.manager = self.webView.page().networkAccessManager()

    self.manager.finished.connect(self.saveExcel)

    postData = QByteArray()

    postData.append("formX=formX&")
    postData.append("formX:idSelecao_input=1&")
    postData.append("formX:dataJanela_input=03/11/2015&")
    postData.append("formX:dataAte_input=07/11/2015&")
    postData.append("formX:j_idt106_input=all&")
    postData.append("formX:j_idt120_input=0&")
    postData.append("formX:produto_input=VLR&")
    postData.append("formX:options=1&")
    postData.append("formX:j_idt133_input=0&")
    #postData.append("javax.faces.ViewState=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&")
    postData.append("formX:j_idt999=formCI:j_idt999")

    self.request = reply.request()
    #self.reply = self.manager.get(self.request)
    self.reply = self.manager.post(reply.request(), postData)

def saveExcel(self):
    f =  open('C:\\path\\to\\file\\searchResults.xls', 'wb')
    f.write(str(self.reply.readAll()))
    f.flush()
    f.close()

    self.exit()

此处有意更改了文件的路径。

我尝试使用post方法以及get方法(在上面的代码片段中注释),但它们都没有工作,我总是最终得到一个损坏的xls文件,它实际上是一个HTML文件,其源代码是页。

当我取消注释postData项&#34; javax.faces.ViewState&#34;时,服务器返回错误。我猜这里是关键所缺少的,因为这条特定线上的特殊字符。

你知道我做错了什么吗?我知道我的方式与python,但我根本不是专家。

如果需要澄清,请告诉我。

我目前正在使用python 2.7.9和PyQT 4.8.7。

1 个答案:

答案 0 :(得分:0)

在这里,我创建了这段代码:

def specialCharsToHtmlHex(self, rawString, jsfViewState=False):
    parsedString = (rawString.replace('+', '%2B')
                             .replace('/', '%2F')
                             .replace(':', '%3A')
                             .replace('?', '%3F'))

    if jsfViewState:
        parsedString = parsedString.replace('=', '%3D')

    return parsedString

我对ViewState进行了这种特殊处理,因为我无法将“=”转换为它们实际上是帖子结构的一部分。

然后我调用了这样的代码:

    postData = QByteArray()

    postData.append(self.specialCharsToHtmlHex("formX=formX&"))
    postData.append(self.specialCharsToHtmlHex("formX:idSelecao_input=1&"))
    postData.append(self.specialCharsToHtmlHex("formX:dataJanela_input="+self.searchData['startDate']+"&"))
    postData.append(self.specialCharsToHtmlHex("formX:dataAte_input="+self.searchData['endDate']+"&"))
    postData.append(self.specialCharsToHtmlHex(self.fieldNames['horaJanela']+"=&")) 
    postData.append(self.specialCharsToHtmlHex(self.fieldNames['tipoPortabilidade']+"=&")) 
    postData.append(self.specialCharsToHtmlHex(self.fieldNames['statusBilhete']+"="+self.searchData['statusValue']+"&")) 
    postData.append(self.specialCharsToHtmlHex(self.fieldNames['operadora']+"=0&"))
    postData.append(self.specialCharsToHtmlHex("formX:produto_input="+self.searchData['productValue']+"&"))
    postData.append(self.specialCharsToHtmlHex("formX:options=1&"))
    postData.append(self.specialCharsToHtmlHex("formX:cpf=&"))
    postData.append(self.specialCharsToHtmlHex(self.fieldNames['janelaBloqueada']+"=0&")) 
    postData.append(self.specialCharsToHtmlHex("formX:dataTable_selection=&"))
    postData.append(self.specialCharsToHtmlHex("javax.faces.ViewState="+self.specialCharsToHtmlHex(self.searchData['jsfViewState'], jsfViewState=True)+"&"))
    postData.append(self.specialCharsToHtmlHex(self.fieldNames['mojarraHiddenInput']+"="+self.searchData['mojarraHiddenValue']))

    self.reply = self.webView.page().networkAccessManager().post(reply.request(), postData)

问题解决了,这样我得到了我想要的Excel文件。

我知道有一些冗余,但为了填充,我决定保留它。