【问题标题】:Python POST Request Not Returning HTML, Requesting JavaScript Be EnabledPython POST 请求未返回 HTML,请求启用 JavaScript
【发布时间】:2016-04-14 22:27:01
【问题描述】:

我正在尝试登录我的 Wells Fargo 帐户并抓取我的交易历史记录,以便我可以使用它们来跟踪我的财务状况。如果我可以访问页面的 HTML,我就可以进行抓取部分。我遇到的问题是到达那里,下面的代码向我返回了很多乱码。

####Bring in BeautifulSoup and urllib.
import bs4
import urllib.request
import requests

####Navigate to the website.
url = 'https://connect.secure.wellsfargo.com/auth/login/do'
payload = {"j_username":"USERNAME", "j_password":"PASSWORD"}
r = requests.post(url, payload)
print(r.text)

此代码输出以下内容:

    <html><head><meta http-equiv="Pragma" content="no-cache"/>

    <meta http-equiv="Expires" content="-1"/>

    <meta http-equiv="CacheControl" content="no-cache"/>

    <script>

    (function(){

        var securemsg;

        var dosl7_common;

    window["bobcmn"] = "1011200000002200000001300000021application/x-www-form-urlencoded3000000088adfa450300000008TSPD_101300000014%2fauth%2flogin%2fdo300000000300000006/TSPD/300000008TSPD_101300000005https3000000b6#sCmnToken#0BC26lnGAWSD9m6NkEoMZy0dIjA7Os6O4oLerWkImSHetiQqPjvoid03xpkXMNwHZ4wUmjd9+FeNk7M7zEe5ESlixC/1O8E7X61l10gL4ddUAhMNR4LaIYlGkq+hckjmRwTXudNvohk90GvOs8Ea9fFIoAAAAAE=#eCmnToken#200000000";



    try{(function(){try{var jS,JS,LS=1,oS=1,OS=1,zS=1,S_=1,__=1,i_=1,I_=1,j_=1;for(var L_=0;L_<JS;++L_)LS+=2,oS+=2,OS+=2,zS+=2,S_+=2,__+=2,i_+=2,I_+=2,j_+=3;jS=LS+oS+OS+zS+S_+__+i_+I_+j_;window.i===jS&&(window.i=++jS)}catch(o_){window.i=jS}var O_=window.sdkljshr489=!0;function z_(S){window.sdkljshr489&&S&&(O_=!1);return O_}function Z_(){}z_(window[Z_.name]===Z_);z_("undefined"===window.vodsS0);window.vodsS0=null;z_(/\x3c/.test(function(){return"\x3c"})&/x3d/.test(function(){return"0";"x3d"}));
    var s_=/mobi/i.test(navigator.userAgent),Si=+new Date,_i=s_?3E4:3E3;function ii(){return z_(Si+_i<(Si=+new Date))}
    (function Ii(){var J=!1;function l(J){for(var l=0;J--;)l+=L(document.documentElement,null);return l}function L(J,l){var Z="vi";l=l||new z;return _S(J,function(J){J.setAttribute("data-"+Z,l.SS());return L(J,l)},null)}function z(){this.O=1;this.L=0;this._=this.O;this.j=null;this.SS=function(){this.j=this.L+this._;if(!isFinite(this.j))return this.reset(),this.SS();this.L=this._;this._=this.j;this.j=null;return this._};this.reset=function(){this.O++;this.L=0;this._=this.O}}var Z=!1;function s(J,l){var L=
    document.createElement(J);l=l||document.body;l.appendChild(L);L&&L.style&&(L.style.display="none")}function iS(l,L){L=L||l;var z="|";function s(J){J=J.split(z);var l=[];for(var L=0;L<J.length;++L){var Z="",lS=J[L].split(",");for(var SS=0;SS<lS.length;++SS)Z+=lS[SS][SS];l.push(Z)}return l}var _S=0,IS="datalist,details,embed,figure,hrimg,strong,article,formaddress|audio,blockquote,area,source,input|canvas,form,link,tbase,option,details,article";IS.split(z);IS=s(IS);IS=new RegExp(IS.join(z),"g");while(IS.exec(l))IS=
    new RegExp((""+new Date)[8],"g"),J&&(Z=O_),++_S;return L(_S&&1)}function _S(J,l,L){(L=L||Z)&&s("div",J);J=J.children;var z=0;for(var _S in J){L=J[_S];try{L instanceof HTMLElement&&(l(L),++z)}catch(IS){}}return z}iS(Ii,l)})();window.oi={iI:"08c787b5a40180002943d30328de8438de8cc553d459dcd4fc6c4cb17feaa34f085900356d674a1888119e0ea122f11994fc63fbabf471ce1f60053949777f087711d376633d1c30cd2e2f14295017cd8afeedacf0c4783d8b9ec0abec9808a830fa17d4cc351f649688f2b9c98cc0961ddcaf13fb0e7020486252f76f751366cdb10741f04ad6fd"};function _(S){return 753>S}function I(){var S=arguments.length;for(var J=0;J<S;++J)arguments[J]-=38;return String.fromCharCode.apply(String,arguments)}function O(S){return S.toString(36)}(function ji(J){return J?0:ji(J)*ji(J)})(ii());var v;})();}finally{sdkljshr489=false;ie9rgb4=void(0);};
    eval((ie9rgb4=function (){var m='function () {/*fQb f_TcC}-di`U_V YU)bWR$+dbikuVe^SdY_^uvkdbikfQb ZCy:Cy<C-!y_C-!y?C-!+V_bufQb <O-}+<O,:C+xx<Ov<Cx-"y_Cx-"y?Cx-#+ZC-<Cx_Cx?C+gY^T_g{Y---ZCssugY^T_g{Y-xxZCvmSQdSXu_OvkgY^T_g{Y-ZCmfQb ?O-gY^T_g{cT[\\ZcXb$()-n}+Ve^SdY_^ jOuCvkgY^T_g{cT[\\ZcXb$()ssCssu?O-n!v+bUdeb^ ?OmVe^SdY_^ JOuvkmjOugY^T_gKJO{^Q]UM---JOv+jOuoe^TUVY^UTo---gY^T_g{f_TcC}v+gY^T_g{f_TcC}-^e\\\\+jOu|Lh#S|{dUcduVe^SdY_^uvkbUdeb^oLh#Somvs|h#T|{dUcduVe^SdY_^uvkbUdeb^o}o+oh#Tomvv+\r\nfQb cO-|]_RY|Y{dUcdu^QfYWQd_b{ecUb1WU^dvyCY-x^Ug 4QdUyOY-cO/#5$*#5#+Ve^SdY_^ YYuvkbUdeb^ jOuCYxOY,uCY-x^Ug 4QdUvvmuVe^SdY_^uvkfQb C-kTUSbi`d*Ve^SdY_^uCvkdbikbUdeb^ :C?>{`QbcUuVe^SdY_^uCvkC-C{c`\\Yduo\\ov+fQb :-oo+V_bufQb \\-}+\\,C{\\U^WdX+xx\\v:x-CdbY^W{Vb_]3XQb3_TUuCK\\Mv+bUdeb^ :muCvvmSQdSXu\\vkmmm+bUdeb^ C-kS_^VYWebQdY_^*C{TUSbi`duo!"#\\#$\\)\'\\))\\!!&\\!}%\\!!(\\!}!\\#$\\%(\\#$\\!!}\\!!!\\#$\\$$\\#$\\!}}\\!}!\\)(\\!!\'\\!}#\\!}#\\!}%\\!!}\\!}#\\#$\\%(\\#$\\!!}\\!!!\\#$\\$$\\#$\\!})\\!!!\\!}}\\!!\'\\!}(\\!}!\\$)\\#$\\%(\\#$\\!}!\\!!}\\)\'\\)(\\!}(\\!}!\\!}}\\#$\\$$\\#$\\!})\\!!!\\!}}\\!!\'\\!}(\\!}!\\%}\\#$\\%(\\#$\\!}!\\!!}\\)\'\\)(\\!}(\\!}!\\!}}\\#$\\$$\\#$\\!})\\!!!\\!}}\\!!\'\\!}(\\!}!\\%!\\#$\\%(\\#$\\!}!\\!!}\\)\'\\)(\\!}(\\!}!\\!}}\\#$\\$$\\#$\\!})\\!!!\\!}}\\!!\'\\!}(\\!}!\\%"\\#$\\%(\\#$\\!}!\\!!}\\)\'\\)(\\!}(\\!}!\\!}}\\#$\\!"%ovmmvuv+\r\ncUSebU]cW-kcZC*Ve^SdY_^uCvkbUdeb^ cUSebU]cWK?u"(()\'vMucUSebU]cW{jYuuOu!&}vy}vyCyOu)""v/}*!vyVe^SdY_^uvkbUdeb^ CdbY^WK9u!$}y!%"y!$)y!$\'y!}%y!$"y!#%y!%"y!}%y!$)y!#(y!#)vMu=QdXK?u"&"}&}!!vMu=QdXK?u!&%}$\'#\'#$vMuvwuOu))#v/#$"*"%&vxuOu""$v/!*}vvruOu")\'v/"%&*#""vvmvK?u)!("#)vMuoovmyjC*Ve^SdY_^uCvkbUdeb^uuCsuOu"%#v/"%%*""}vv,,uOu)$\'v/"!*"$vluCsuOu$(&v/&%"(}*&&%%%vv,,uOu)}!v/%*(vlC..uOu(()v/)*(vsuOu&&"v/&%"(}*\'##\'\'vlC..uOu%%)v/"$*#"vsuOu!&$v/"%%*#"\'vv...uOu!)"vy}vmy9}*Ve^SdY_^uCy:vkV_bufQb \\-ooy<-uOu%&)vy\r\n}v+<,CK?u!")$#))"}%vM+<xxv\\x-CdbY^WKoLe}}&&b_]3Lh&(Qb3_TUoMuCK9u!#\'y!$"y!#%y!%"y!}%y!$)y!#(y!#)y!}#y!%$vMuu<xCK?u!")$#))"}%vMz:vrCK?u!")$#))"}%vMvv+bUdeb^ \\myYZC*Ve^SdY_^uCy:vkbUdeb^ cUSebU]cW{9}uCyCK?u!")$#))"}%vMz:vmy<O*Ve^SdY_^uCy:vkYVuCK?u!")$#))"}%vMn-:K?u!")$#))"}%vMvdXb_g cUSebU]cW{:CuCvycUSebU]cW{:Cu:vyoo+V_bufQb \\-ooy<-uOu\'&#vy}v+<,CK?u!")$#))"}%vM+<xxv\\x-CdbY^WKoLe}}&&bLh&V]Le}}$#XLh&!bLe}}$#_Lh&$UoMuCK9u!#\'y\r\n!$"y!#%y!%"y!}%y!$)y!#(y!#)y!}#y!%$vMu<vN:KoLe}}&#XQbLh$#_TU1doMu<vv+bUdeb^ \\my<C*Ve^SdY_^uCy:vkbUdeb^uuC...uOu""!vy}vvxu:...uOu"")vy}vvsuOu)$&v/"!$\'$(#&$\'*$")$)&\'")%vv...uOu&$#vy}vmyO:*Ve^SdY_^uCy:vkbUdeb^uuC...uOu()(vy}vvz:suOu!}&v/$")$)&\'")%*"!$\'$(#&$\'vv...uOu#\'}vy}vmy_%*Ve^SdY_^uCy:y\\vkdbikYVuCK?u!")$#))"}%vMn-uOu("#v/""*!&vvdXb_goo+YVu:K?u!")$#))"}%vMn-uOu&}&v/(*&vvdXb_goo+fQb <-cUSebU]cW{c_uCv+<KOu()vy}M-cUSebU]cW{jCu<KOu\'(&vy}Mv+<KOu\'(#v/}*!M-cUSebU]cW{jCu<KOu)!(v/\r\n}*!Mv+<KOu)"(v/!*"M-cUSebU]cW{jCu<KOu&\'}vy"Mv+<KOu\'(%v/"*#M-cUSebU]cW{jCu<KOu!\')vy#Mv+fQb j-cUSebU]cW{c_u:vyJ-cUSebU]cW{jCujKOu\'$}vy}Mvyc-cUSebU]cW{jCujKOu(\'}v/}*!MvyYC-u\\/Ou)"&v/"!$\'$(#&$\'*$"$\'})\'"#}$*uOu)&#vy}vv...uOu$\'#vy}v+YVu\\vV_bufQb OC-Ou""!v/!%*!"+OC.-uOu"%#vy}v+OCzzvfQb CC-cUSebU]cW{<CuJ,,uOu#\'%v/$*#vNJ...uOu$#%v/%*#vyJvy\\C-cUSebU]cW{<CuYCy<KYC...uOu""#v/!!*!}vsuOu"}\'v/#*"vMvyc-cUSebU]cW{O:ucyCCN\\CvyYC-cUSebU]cW{O:uYCyOu"}%v/"&%$$#%\'&)*"!$!&$}&("vycC-cUSebU]cW{<Cuc,,uOu\'\'\'vy$vNc...uOu!\')v/\r\n%*"vycvyJC-

*************************************************************

""}"!&2) %%}%"&"6 3%21#225 2"24}2"( "22$%1)" %32#&1}$ 3"4\'661\' 2%4}36#! "34))5(2 %24515!4 )2&$3"2} 53&#6""& \'%&11#)3 }"&4)#}1 )3})}&1) 52}5#&#6 \'"}\'&\'(% }%}}%\'!# )%26$1(" 5"2(\'1!$ \'22!"215 }32&!2#( )"4"(5)2 5%4%25}4 \'343562\' }24246"! (&4#4"4$ 6!4$5"$" &(442#6( !641(#&5 (!25!&34 6&2)"&%2 &62}\'\'5! !(2\'$\'\'\' ((}(%15& 66}6&1\'} &&}&#231 !!}!}2%3 (6&%)566 6(&"15&) &!&2664# !&&336$% 1}}15"\'( 4\'}44"55 $5}$(#%$ #)}#2#3" 1\'&\'"&&! 4}&}!&6\' $)&)$\'$4 #5&5\'\'42 154!&1$1 4)4&%143 $}46}2&& #\'4(#26} 1)2315%# 4522)53% $\'2"36\'6 #}2%665) 24246"!3 31213"(1 %#2#)##} "$2$1#1& 214}#&}% 344\'}&)# %$45%\'") "#4)&\'26 2#&&\'1"5 3$&!$12( %4&(!2}" "1&6"2)$ 2$}225#\' 3#}3(51! %1}%46!2 "4}"56(4oK?u!\'$#))!)(#vMuuu\\ON\r\n9CK9u!#\'y!$"y!#%y!%"y!}%y!$)y!#(y!#)y!}#y!%$vMu\\vvsuOu$&&v/"%%*#\'!vvwuOu\'!!v/)*&vyOu"}!v/(*!!v+\\ON-uOu$!$vyz!v+\\O-=QdXK?u!##($vMu\\Ov+\\On-`QbcU9^duJv/uJCxxycUdDY]U_eduCyuOu!#}vy}vvv*:uvmU\\cU :uvmVe^SdY_^ :uvkfQb C-cUSebU]cWK?u!#"$()#vMu:Ox9u)&vxcxoLe}}#QoxYCx9u)&vx\\OyoLh#}Le}}##ov+T_c\\\'OS_]]_^{9Ju<yCyooyOu"($v/%5#*$}\'#yYYuvvmV_bufQb \\-cUSebU]cW{?CugY^T_g{_Y{Y9yoLe}}#}Lh#!ovy\\-T_c\\\'OS_]]_^{::u\\yn!vy<-cUSebU]cW{:Cu\\KOu&#"vy}Mvy\r\nj-\\KOu!!#v/!*}MyJ-\\KOu$&v/"*!Myc-\\KOu!)%v/#*"MyYC-\\KOu&&#vy$MyOC-\\KOu(%$vy%MyCC-\\KOu$}\'v/&*#MK9u!#\'y!$"y!#%y!%"y!}%y!$)y!#(y!#)y!}#y!%$vMuuOu$$&vy}vvy\\C-1bbQiujvycC-=QdXK?u##")&vMuCCzOCKoLe}}&#Lh&(Le}}&!Lh\'"Le}}$#Lh&VLe}}&$Lh&%Le}}$!Lh\'$oMuuOu&%$vy}vvxuOu!)"v/!*}vyjvyJC-uOu\'"%vy}v+JC,j+JCxxv\\CKJCM-OC+fQb JC-uOu)"}vy}vy:Oy9Cy\\O+cUdDY]U_eduCyuOu"\'\'vy}vvmv+\r\nVe^SdY_^ OuCvkbUdeb^ \'%#.CmVe^SdY_^ 9uvkfQb C-QbWe]U^dc{\\U^WdX+V_bufQb :-}+:,C+xx:vQbWe]U^dcK:Mz-#(+bUdeb^ CdbY^W{Vb_]3XQb3_TU{Q``\\iuCdbY^WyQbWe]U^dcvmVe^SdY_^ ?uCvkbUdeb^ C{d_CdbY^Wu#&vmuVe^SdY_^ ZYu:vkbUdeb^ :/}*ZYu:vwZYu:vmvuYYuvv+fQb f+mvuv+mVY^Q\\\\ikcT[\\ZcXb$()-VQ\\cU+YU)bWR$-f_YTu}v+m+*/;}'.slice(15,-4);for(var i=0,c=8,j=0,l,r='';l=m.charCodeAt(i);++i)c=String.fromCharCode(l<33||l>=126?l:(93+l-((-76E-3+''+({}).a).slice(7).charCodeAt(j%'1')))%93+33),r+=c,j-=c.indexOf('\x0d');return r;})());

    })();

    </script>

    <noscript>Please enable JavaScript to view the page content.</noscript>

    </head><body>

    </body></html>

我为可怕的格式道歉,但我不知道如何处理它。此外,为了长度,我删除了中间的一个大的任意部分,我用星号替换了。

对我来说,我看到的关键是“请启用 JavaScript 以查看页面内容”。这个输出实际上是 JS 吗?我如何用 Python 处理它?我根本不知道这告诉我什么,我非常感谢您提供的任何帮助。

谢谢。

【问题讨论】:

    标签: javascript python-3.5


    【解决方案1】:

    一些使用 javascript 的网站不能仅仅通过下载 html 并将其传递给 html 解析器来抓取,因为内容根本不存在。通常发生这种情况是因为页面包含一个脚本,该脚本会下载真实信息并将其插入到 DOM 树中。

    在这种情况下,仅下载网站是不够的,您需要一个支持 JavaScript 的 Web 浏览器引擎,您可以通过 Python 进行控制。

    这里有一个您可以使用的项目列表:https://github.com/dhamaniasad/HeadlessBrowsers,它们支持不同的编程语言。我使用过 Selenium,它运行良好,但我不确定是否支持 Python 3.5。

    【讨论】:

    • Dyeray,我看到你又来帮助我了。我非常感谢您的帮助。我希望避免这条路线只是为了保持精简和快速,但我没有理由不能使用浏览器。谢谢。
    • 如果网站使用 ajax 调用来获取内容,您可以直接调用这些 url。他们有可能使用的是一个宁静的网络服务,这甚至比抓取更好。
    【解决方案2】:

    我知道这已经过去了很长时间,但我可以在这里做一些总结。您所看到的是由F5 Networks, Inc. 的好人出售的机器人失败代码,旨在防止天真的网络爬虫和爬虫能够访问使用它的网站。

    简而言之,这是一种混淆的 Javascript,它通过一系列迭代步骤来计算一个值,这些步骤锻炼各种特定于浏览器的 Javascript 功能,并利用一些相当粗鲁的 Javascript 语言行为。该值作为 cookie 和导航所需的部分网络表单发送回富国银行。仅仅使用无头浏览器并不能解决问题 - 计算中有一些技巧专门用于对抗无头浏览器和与它们一起工作的 Javascript 引擎。错过任何技巧都不会导致任何失败;相反,它只会以一种让你很难说出你错过了什么的方式抛弃最终结果。

    理论上,可以用您选择的语言破译代码并模拟所有计算;我知道一家数据聚合公司编写了一个成功的对策,但代码不开放供公众阅读。或者,您可以找出在 JS 解释器中按原样正确执行它所需的内容。我不记得所有的细节,但它比看起来容易。你不需要对整个事情进行逆向工程,你只需要在正确的环境中运行它。您需要一个虚拟窗口对象和更多虚拟对象,用于代码在您的环境中寻找的任何其他东西,例如 navigator.userAgent,可能还有其他东西。

    出于实际目的,编写对策可能不值得。如果您是组织,请要求将其列入白名单。

    如果您对挑战感兴趣,这里有一个(可能很明显)起点 - eval((ie9rgb4=function (){var m='function () ... .slice ... 部分中的一长串乱码是加密代码。紧随其后的 for 循环包含字符转换。您可以复制在该循环中执行的操作以破译第一级混淆。在调试器处于活动状态的情况下,通过您的普通浏览器登录该站点,观察发送的请求和 cookie 以了解您正在寻找的最终目标,并尝试将其与您看到的 JS 代码相关联。

    您可能还会发现以下值的映射在某些时候很有用:

    {"$$$", "7"},
    {"$$$$", "f"},
    {"$$$_", "e"},
    {"$$_", "6"},
    {"$$_$", "d"},
    {"$$__", "c"},
    {"$_", "constructor"},
    {"$_$", "5"},
    {"$_$$", "b"},
    {"$_$_", "a"},
    {"$__", "4"},
    {"$__$", "9"},
    {"$___", "8"},
    {"_", "u"},
    {"_$", "o"},
    {"_$$", "3"},
    {"_$_", "2"},
    {"__", "t"},
    {"__$", "1"},
    {"___", "0"}
    

    【讨论】:

    • 你好双陆棋。看到你的帖子,想了解更多信息。如何在返回的 javascript 中处理 --- eval((ie9rgb4=function (){var m='function () ... .slice ---- 。您是否需要运行一个 javascript 解释器——类似于nodejs。我们看到了类似的东西,并且有兴趣进一步了解混淆数据包含的内容。谢谢
    • 这部分很简单,因为它是独立的。您不需要任何框架,只需一个普通的旧 JS 解释器即可。执行函数体内的语句(分配给m 和下面的for 循环)。检查r 的内容以获取破译代码。您应该有一个以var vodsS0=typeof ie9rgb4;... 开头的字符串。内容只是更加模糊的代码。你仍然需要弄清楚它想要做什么。如果您查看整个 bot-defeat 代码,它会将此类数据的三个不同块作为函数解密并执行。
    • 如果您想克服这个问题,我建议您尝试不同的解决方案,例如要求被列入白名单。如果你有决心——我不记得所有的细节,但它比看起来容易。你不需要对整个事情进行逆向工程,你只需要在正确的环境中运行它。您需要一个虚拟的 window 对象和更多的虚拟对象,用于代码在您的环境中寻找的任何其他东西,例如 navigator.userAgent,也许还有其他东西。
    【解决方案3】:

    可以通过Splash(Selenium 之外的另一个 JS 渲染器)来使用。因为我使用 Scrapy,所以我使用 Scrapy-Splash。在我的 Scrapy spider 中,我使用 Splash,但不仅如此。 Splash 请求应该使用 lua 脚本来帮助获取额外的命令以从网页获取 cookie,否则它仍然会被 F5 安全机制阻止。获取 cookie 后,使用生成的 cookie 重新请求页面,完成!

    Scrapy 中的代码会是这样的:

    def start_requests(self):
        lua_script = '''
        function main(splash)
          local url = splash.args.url
          assert(splash:go(url))
          assert(splash:wait(2))
          return {
            html = splash:html(),
            cookies = splash:get_cookies(),
          }
        end
        '''
        yield SplashRequest(self.start_urls[0], self.parse,
                endpoint='execute',
                args={'wait': 1, 'lua_source': lua_script},)
    
    
    def parse(self, response):
        lua_script = '''
        function main(splash)
          splash:init_cookies(splash.args.cookies)
          local url = splash.args.url
          assert(splash:go(url))
          assert(splash:wait(2))
          return {
            html = splash:html(),
          }
        end
        '''
        yield SplashRequest(self.start_urls[0], self.parse_result,
                endpoint='execute',
                args={'wait': 1, 'lua_source': lua_script},dont_filter=True)
    
    def parse_result(self, response):
        # Do your scrapy parsing thing here
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2013-02-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-10-26
      • 2023-01-21
      • 2021-07-10
      相关资源
      最近更新 更多