当前位置:网站首页>Per capita Swiss number series, Swiss number 4 generation JS reverse analysis

Per capita Swiss number series, Swiss number 4 generation JS reverse analysis

2022-07-06 23:22:00 VIP_ CQCRE

This is a 「 Attacking Coder」 Of the 656  Technology sharing

author :K The little elder brother

source :K Brother reptile

It is necessary to read this article 13 minute .

c512798e4b455fb16bcff4b9ff1e3355.png

Statement

All the contents in this article are only for learning and communication , Not for any other purpose , The complete code is not provided , The content of the package 、 Sensitive website 、 The data interface has been desensitized , It is strictly prohibited to use for commercial and illegal purposes , Otherwise, all the consequences have nothing to do with the author !

This article is forbidden to be reproduced without permission , Prohibit any secondary dissemination after modification , Any accident caused by unauthorized use of the technology explained in this article , The author is not responsible , If there is infringement , Please be in the official account. 【K Brother reptile 】 Contact the author to delete it immediately !

Preface

be538ef852fa5ef330d411b33bbae37d.png

Swiss dynamic security Botgate( Robot firewall ) With “ Dynamic security ” Technology is the core , Through dynamic encapsulation 、 Dynamic validation 、 Dynamic confusion 、 Dynamic token and other technologies continuously and dynamically transform the underlying code of the server web page , Increase server behavior “ Unpredictability ”, It realizes the omni-directional from the client side to the server side “ Active protection ”, For all kinds of Web、HTML5 Provide strong security protection .

Rayleigh number Botgate It is mostly used in government and enterprises 、 Finance 、 Carrier industry , It was once regarded as climbing the ceiling , With the increasing number of reverse bosses in recent years , Relevant reverse articles also emerge in endlessly , It's really the age of Swiss per capita , Here also thanks for things like Nanda、 Lazy God and other reverse bosses , Unveil the mystery of ruishu , The experience summed up made later people take many detours less .

There are basically the following methods for crossing Rayleigh number : Automation tools ( To hide characteristic values )、RPC The remote invocation 、JS reverse ( Hard deduction code and supplementary environment ), This article introduces JS Reverse hard deduction code , Introduce as many details as possible .

The characteristics of Rayleigh number and the differences between different versions

For the vast majority of websites that use RSL , It has the following characteristics ( There may be special versions that are different , First, just look at the mainstream ):

1、 Open developer tools (F12) There will be two typical infinite debugger:

ff4f4f8ab9adc7db712a68f71c51cca9.png

82af0169a7bac36a4df5610080b8ab67.png

2、 Rayleigh number JS Obfuscate code , Variable 、 Method names are mostly similar to _$xx, There are many if-else control flow , The new Swiss number may also have jsvmp And the situation of many ternary expressions :

9a4402a39e90c7c518a073933ada7e81.png


3、 Look at the request , There will be three typical requests , The first request response code is 202( Rayleigh number 3、4 generation ) perhaps 412( Rayleigh number 5 generation ), Then request a separate JS file , Then re request the page , Other follow-up XHR In request , With a suffix , The value of this suffix is determined by JS Generated , It changes every time , The first number of the suffix value is the Swiss number version , such as MmEwMD=4xxxxx Namely 4 Dari number ,bX3Xf9nD=5xxxxx Namely 5 Dari number :

6e46bccd41ba1bac11c1a37ae54ee0c7.png

c72d9ce3b1aa5b15afd287e2afcc2e9a.png

a91d71cb1565000cd80f6ed8038e43d3.png

855b696b0c7b396a26b50c2bb357424f.png

4、 see Cookie, Rayleigh number 3、4 Replace with T and S The two at the end Cookie, Among them S At the beginning Cookie For the first time 201 That request returned , With T At the beginning Cookie By JS Generated , Dynamic ,T and S The front is usually followed by 80 or 443 The number of ,Cookie The first number of the value is the version of Rayleigh number ( Why can we judge the version by the first number ? Won't the first number of the same version change ? We are analyzing these problems JS The answer can be found when ), such as :

  • FSSBBIl1UgzbN7N80T=37Na97B.nWX3....: Numbers 80 yes http The default port number of the protocol , Corresponding http request , The first place of its value is 3, Express 3 Dari number ;

  • FSSBBIl1UgzbN7N443T=4a.tr1kEXk.....: Numbers 443 yes https The default port number of the protocol , Corresponding https request , The first place of its value is 4, Express 4 Dari number .

aa478e47254cbddea4fbca33f6cc7783.png

Rayleigh number 5 There are also generations with T and S The two at the end Cookie, But there's something special 5 Dai Rui number also has O and P At the end of the , alike , With O The beginning is the first 412 That request returned , With P The beginning is by JS Generated ,Cookie The first number of the value is also the version of Rayleigh number , and 3、4 The difference between generations is ,5 I didn't add the port number , such as :

  • vsKWUwn3HsfIO=57C6DwDUXS.....: With O ending , The first place of its value is 5, Express 5 Dari number ;

  • WvY7XhIMu0fGT=53.9fybty......: With T ending , The first place of its value is 5, Express 5 Dari number .

5c264afd75bc73a6b3bdc904619bd8ac.png

e3a47d522888339694d6c3812c7ebc61.png

5、 Look at the entrance , Ruishu has a process in the virtual machine VM Load in 1w+ Lines of code , The entry to load this code , Different versions are also different ( Where exactly is this entrance ? How to locate ? It will be introduced in detail in the subsequent reverse analysis ), Examples are as follows :

  • 3 generation :_$aW = _$c6[_$l6()](_$wc, _$mo);,_$c6 It's actually eval,_$l6() It's actually call;

2f4418cd30cb11ebbe9f4aacdf8e35fd.png

  • 4 generation :ret = _$DG.call(_$6a, _$YK);,_$DG It's actually eval, There are keywords ret,call It's plain text ;

0103f69c217672cf7e7d9b9151126b0c.png

  • 5 generation :5 There are many kinds of generations , Initially and 4 Generation is similar , such as ret = _$Yg.call(_$kc, _$mH);, There are keywords ret,call It's plain text , There is no ret The version of the keyword , such as _$ap = _$j5.call(_$_T, _$gp);, Also like 3 Generation is all confused , such as :_$x8 = _$mP[_$nU[15]](_$z3, _$Ec);,_$mP It's actually eval,_$nU[15] It's actually call, confused call And 3 The difference between generations is 5 Generation is obtained by taking values in an array ;

07aba42918388facaedb1d94e9798150.png

47b51bc9b28266aafd48eee82b20d284.png

940b6e9d39f8f21314c1b8af157c4a4c.png


Of course, to accurately distinguish different versions , All conditions must be combined , The most important thing is to look at the internal implementation logic , And the code structure of the page , such as 4 Generation has a generation false Cookie Steps for , and 5 No generation , Although some special versions seem to be 5 generation , But added jsvmp And trinocular expression , And traditional 5 There are differences between generations , Occasionally, there is a new version of April Fool's day , It will be different , After analyzing each version , It's easy to distinguish .

Cookie Entrance positioning

Swiss number in this case 4 The proxy website is :aHR0cDovL3d3dy5mYW5nZGkuY29tLmNuL25ld19ob3VzZS9uZXdfaG91c2VfZGV0YWlsLmh0bWw=

First of all, go beyond infinity debugger( But it doesn't matter , In the later analysis, this basically has no effect ), Right click directly Never pause here Never disconnect here :

5e1a0ec667d25e5d9103ae6dfd99012d.png


location Cookie, The preferred Hook The fastest to come , adopt Fiddler Wait for bag grabbing tools 、 Oil monkey script 、 Browser plug-ins and other ways to inject the following Hook Code :

(function() {
    //  Rigorous model   Check all errors 
    'use strict';
    // document  For hook The object of   Here is hook Of cookie
 var cookieTemp = "";
    Object.defineProperty(document, 'cookie', {
  // hook set Method is the method of assignment  
  set: function(val) {
    //  In this way, you can quickly break the following code line 
    //  So as to quickly locate the settings cookie Code for 
    console.log('Hook Capture to cookie Set up ->', val);
                debugger;
    cookieTemp = val;
    return val;
  },
  // hook get  Method, that is, the method of value  
  get: function()
  {
   return cookieTemp;
  }
    });
})();

Hook It is found that there will be two generation Cookie The situation of , After disconnection, follow the stack up , You can see the assembly Cookie Code for , Similar to the following structure :

7fc2f52df35b3253adb265d7930272eb.png


Observe these two times carefully Cookie Generated place , Follow the stack up separately , You will find two Cookie They are obtained through two different methods , As shown in the figure below :

9461910ac7355352aa4443f38c2231f7.png

a17fb26a411650efc9cd732ab6bdf737.png


The code here exists in VM In the virtual machine , And is IIFE Self executing code , We have to follow the stack to see these VM Where is the code loaded , Follow the stack to the home page (202 page ) with call The location of :

3c7559cda44533af7504c3b395b5e70a.png

This is the position we introduced at the beginning of the article , This position is usually used as an entry when analyzing the Rayleigh number , In the figure _$te It's actually eval Method , The first parameter passed in _$fY yes Window object , The second object _$F8 It's what we saw earlier VM In the virtual machine IIFE Self executing code .

After knowing the approximate entrance of Rui number , We can also use Script The breakpoint , Go to the next breakpoint (F8) You can walk to 202 page , And then the search call Keywords can quickly locate the entry ,Script Two options in the breakpoint , The first one means running JS The first statement of the script breaks , The second means JS Cut off when blocked due to content security policy , Usually choose the first one , As shown in the figure below :

b0b8fc86992ae6479db300149d0a03b7.png

File structure and logic

Want follow-up analysis Cookie Generation , We have to observe 202 Page code ,meta The label has a content Content , A reference similar to c.FxJzG50F.dfe1675.js Of JS file , Then follow a self executing JS, As shown in the figure below :

390248bb850f63a62f63f436b2d04c2d.png


The first 1 part meta Labeled content Content , It changes every time , The first 2 Part of the referenced external JS There are also differences on different pages , But the same website, the same page JS The content in is usually fixed and will not change , The first 3 Part of the self executing code changes only the variable name each time , Global logic invariance , Later, when we deduct the code , Some of the methods here will also be used . There are also many self executing codes if-else control flow , The first array , Like the one above _$Dk It is used to control the subsequent control flow .

Refer to the c.FxJzG50F.dfe1675.js It's garbled when you open it directly , And self execution JS The main function of is to make this JS The garbled code is restored to VM Inside 1w+ Normal code of line , And define a global variable window.$_ts And assigned many values , This variable follows VM It plays a very important role ,meta Labeled content The content will also be in VM Used in .

Because of many values 、 Variables are dynamic , Certainly not conducive to our analysis , So we need to fix a set of code to the local , Breaking point 、 It will be more convenient to follow the stack , Keep a random copy 202 Page code , And the corresponding outer chain of this page JS file , Such as c.FxJzG50F.dfe1675.js To local , Use the browser's own overrides Rewriting function 、 Or browser plug-ins ReRes、 Or the response replacement function of the packet capturing tool ( Such as Fiddler Of AutoResponder) Replace .

c6d1c2b16a62510868277466c072bea4.png

VM The code inside is generated Cookie The main code of , Contains many if-else control flow , Undoubtedly, it increases the cost of analyzing the code , You can use AST Technology to do some anti confusion , such as Nanda will if-else The control flow is transformed into switch-case Of , The code under the same control flow is placed in the same case Next , And then in call The place at the entrance , take VM Make a local replacement of the code , For details, please refer to Nanda The article :《 A certain number 4 Generation logic analysis 》, You can try what you are interested in , Don't understand AST You can see the previous articles 《 Reverse progression , utilize AST Technical restoration JavaScript Obfuscated code 》, Time for follow-up K Brother, write again AST The actual battle of restoring Swiss number code , In this article, we choose rigid !

16013e7c3f8ececdbad90eaf7d187170.jpeg

VM Code and $_ts Variable acquisition

We learned about VM Code and $_ts Importance , So our first step is to find a way to get them , As for when it will be useful , Later in the article , Copy the outer chain JS, namely  c.FxJzG50F.dfe1675.js The code and 202 Page self executing code to file , Just run it locally , The environment needs to be slightly supplemented , Lack of Han make up what , Make up roughly window、location、document That's it , The specific content of the supplement can be directly used in the browser console copy() Copy the command , then VM Code, we can directly Hook eval The way to get , The approximate supplementary environment code is as follows :

var eval_js = ""

window = {
    $_ts:{},
    eval:function (data) {
        eval_js = data
    }
}

location = {
    "ancestorOrigins": {},
    "href": "http://www. Desensitization treatment .com.cn/new_house/new_house_detail.html",
    "origin": "http://www. Desensitization treatment .com.cn",
    "protocol": "http:",
    "host": "www. Desensitization treatment .com.cn",
    "hostname": "www. Desensitization treatment .com.cn",
    "port": "",
    "pathname": "/new_house/new_house_detail.html",
    "search": "",
    "hash": ""
}

document = {
    "scripts": ["script", "script"]
}

d11195087d05929690dc264af11edaaf.png


Observe $_ts Of key and value, It's the same as what you get in the browser :

7dd30e1fdbb594a07c1faddc9e18a305.png


matters needing attention :c.FxJzG50F.dfe1675.js Outside the chain JS If you download it directly and open it with an editor, it may be automatically encoded , It is different from the original data , This will cause an error in operation , It is recommended to access this file online directly in the browser , Copy it manually , Or copy the response content in the packet capturing software , Observe the following two situations , The first situation may lead to running errors , The second is normal :

3e89a6255b1d1935855ad59b03f12440.png


Deduction code

So much for that , Now we can finally enter the theme , That is the deduction code , Find a good chair , Ready to put your ass on , At this time, your keyboard only F11 Useful , Continuous single step debugging , Only a hundred million details are needed , It's over !

There are too many code steps , It's impossible to write screenshots at every step , Just write something important , If there is anything missing , There's no way 7492a14d75b2b110f5e735571799f498.png, First, let's replace 202 In the page , Manually add... From the beginning of code execution debugger, As soon as you enter the page, it will be disconnected , Facilitate subsequent analysis :

b05b3336ed988e5d282055cd6de18795.png


Through our previous analysis , I already know the entrance is call The place of , Quickly search and place breakpoints :

4bb96e91f901d679979e4477ffbf68d1.png

Through our previous analysis , We also know that there are two generation Cookie The place of , Quick search (5), The second search result is the entry :

5f4662a871977e877a7791664f08c35b.png

false Cookie Generative logic

First of all, one step with fake Cookie, Although it's fake , But subsequent life comes true Cookie Will be used in , When you follow, you will come to this logic :

84ffee36c0458073189731f69bacdf0d.png

One step will call _$8e() Method , and _$8e = _$Q9,_$Q9 Nested in _$d0 Inside , Search where to call _$d0, Discovery is the beginning of the code :

dcd405f5e75af689d5363f2ae53f81b1.png

So the parameter passed in _$Wn What is? ? Step into , It's a method , The function is to take 202 Page content Content , Then we will delete this locally _$Wn Method , Direct in content The value of the can , As shown in the figure below :

ead32c0d3eac3f9ffc266cd48ef67c4b.png


in addition , We found that , The code has a lot of cases of taking values by index in the array , Like the one above _$PV[68] Value , It's actually a string content, Obviously, we need to find the source of this array , Search directly _$PV =, You can find the suspected definition and assignment :

19a159955cbf38d78ef4e73d9a38bef6.png

3dc93944278b2d3c75e112b735980581.png


So we have to look at this _$iL Method , A very long string was passed in , Break in and have a look , Sure enough _$PV, It's a 725 Bit array :

47fcce92fc57334cf45f8ad3b16f131f.png

Next, in the process of deducting the code , You will often encounter a variable , In this article is _$sX

43648e589d6bb22d6cb35e00d54b82be.png


Are you familiar with ? This value is what we got earlier $_ts Variable , You can see at the beginning that it will window.$_ts Assigned to _$sX

bf2125b761e747f16e80885de16f3c9f.png

Continue to go , Will go to the following logic :

e4f653c71eb4ea412537bf74d6c7ad5c.png

Here we will encounter six arrays , They are already worth it , So we have to find out where they came from , Search any one of the array names , You will find the place of definition and assignment :

9cb371f15c0bce4a1e73a3e7a4715659.png

0d8594065ada87a913939310f65c739b.png


Assignment obviously calls _$rv Method , Search again _$rv Method , It is found that :

10757c69ab584cbb1f84ebe817a1d6a3.png

There is nothing special in the follow-up , Always single step , The last one join('') operation , A false is generated Cookie:

e12d2d9f42a18394483608cca3723576.png


Pick up Next is generation Cookie Name FSSBBIl1UgzbN7N80T , And then Cookie Assign a value to document.cookie , And then to localStorage Inside $_ck Assigned a value , localStorage The content of can be copied directly , It doesn't have a big impact .

953b9b1d6d7693458765ee53faef7081.png


really Cookie Generative logic

One step with truth Cookie, In this paper, that is _$ZN(768, 1);, You can see the beginning of endless if-else control flow :

e113b04baff306a9c82792998f21f465.png

How should we deal with it locally ? My approach is to _$Hn And its value name function ,function _$Hn768(){} It means that all go 768 No. 1 control flow method , Keep following , Generating truth Cookie The method is basically 747 No. control flow , In the follow-up, we mainly focus on 747 From the various steps of the control flow ,747 The code deducted from the No. 1 control flow is roughly as follows :

523b4035c7b23b8015f9d699aa0c168f.png

Take false Cookie

One step heel 747 No. control flow , There will be an entry 709 No. 1 control flow steps , Will take the previously generated false Cookie, After a series of operations, an array is returned :

f8084468ed1f7776a41d8699836f952d.png

c242fd8546de196460756c58d0f7d0d1.png


So far, we have synchronized the code of the buckle locally , If it's normal , The returned array should be the same ( The subsequent data is different , There are some parameters such as timestamp involved in the operation ):

a7b74f6854abacf6790f66ed325f0295.png

Automated tool detection

Keep following 747 No. control flow , Will enter 268 No. control flow , Then enter the 154 No. control flow , There will be some tests for automated tools , As shown in the figure below :

817b7eb5ccea6bc78466c51f33295814.png

d712ffb64bf316a9acce71efdcd09003.png


Here we define a variable _$iL, If the test fails, it means 1, Then I assigned this variable to _$aW, So we are consistent locally , Also for the false that will do ( In fact, if we don't use automated tools , This detection does not need to be returned directly false Just go ):

9b06a36a92bcf3c71542655bf74a035c.png

20 Bit core array

Keep following 268 No. control flow , Will enter 668 No. control flow ,668 There are only two operations in the No. 1 control flow , One is to generate a 16 Digit group , Second, take $_ts Inside 4 A variable , Add to the front 16 Bit back , Form a 20 Digit group , this 20 The last of the digit group 4 Bit is the core of Rayleigh number , The mapping relationship is wrong, and the request cannot pass , In the five generations, the processing logic of this part will be more complex .

90c54a8cc2293ca0a2b3e56b4b66add1.png

c2b095510fae9bba9ccbc88640b8ee0f.png


This is not simply taking $_ts The key value in the , When you deduct the code , You may find out how to get values here locally , What is taken out is not a number , It's a string ? It's like this :

ce2b8479c8d44d5e45c599024aa9a74f.png

In fact, what we first got $_ts value , It has been processed twice , We take the first _$sX._$Xb For example , Search directly _$sX._$Xb, You can find such a place :

f91ede74b6da2763a79610725affa92d.png

Obviously, here is  _$sX._$Xb Re assigned again , We can see to the right of the equal sign , I took it first _$sX._$Xb, Its value is _$Rm, This is different from our initial $_ts The corresponding values are the same , Then we have to look again _$sX["_$Rm"] What is sacred , Direct search finds a method assigned at the beginning , Generate new values by calling this method :

8aa60acf560ab0a101041f9d92173fa3.png

The other three values are the same routine , The assigned codes are :

_$sX._$Xb = _$sX[_$sX._$Xb](_$BH, _$DP);
_$sX._$oI = _$sX[_$sX._$oI](_$ZJ, _$DS)
_$sX._$EN = _$sX[_$sX._$EN]();
_$sX._$D9 = _$sX[_$sX._$D9](_$iL);

It should actually be :

_$sX._$Xb = _$sX["_$Rm"](_$BH, _$DP);
_$sX._$oI = _$sX["_$Nw"](_$ZJ, _$DS)
_$sX._$EN = _$sX["_$Uh"]();
_$sX._$D9 = _$sX["_$ci"](_$iL);

Further on , It's actually :

_$sX._$Xb = _$1k(_$BH, _$DP);
_$sX._$oI = _$jH(_$ZJ, _$DS)
_$sX._$EN = _$9M();
_$sX._$D9 = _$oL(_$iL);

Static analysis is ok , We can fix it first , But in practical application, these values are dynamic , So what should we do ? First, let's look at a few more and compare them to find the rules :

371587f81647e6cf3980b23192d9836a.png

6faf87dbef1e477f428422deb086ee3f.png


You can find that the corresponding order is different every time , But in fact, the method of clicking in the same position is the same , in other words , Only the method name and variable name are changed , The logic of implementation is unchanged , So we only need to know the corresponding positions of these four values , You can get the correct value , In the local , We can do that :

1、 First, use regular matching to find these four values , Such as :[_$sX._$Xb, _$sX._$oI, _$sX._$EN, _$sX._$D9];

207fddb46eb9c810cbd26c4b8669f570.png


2、 Then match VM At the beginning of the code 20 An assignment statement , Such as :_$sX._$RH = _$wI; _$sX._$i5 = _$n5; etc. ;

9f80b8365bc33d95fe40de38446992d5.png


3、 And then through $_ts Take the value corresponding to these four values , amount to :_$sX._$Xb = _$ts._$Xb = _$Rm; Then find the method defined by these four values in 20 Position in an assignment statement , amount to : lookup _$sX._$Rm = _$1k; stay 20 The position in the assignment statement is 7( Index from 0 Start )

6a44d08725c6c30825fb612d2972e403.png

4、 We know that these four methods are 20 Position in an assignment statement , Then we directly match the name of the local corresponding location , Dynamic replacement is enough , Of course, the premise is that we have deducted a set of codes locally :

86f226bb1ebfde5bd7d3f564097d874a.png

e1b7bf8a65b33570df1e4b6366faa71e.png


After this treatment , The accuracy of these four values can be guaranteed .

Other uses $_ts Where it's worth it

Other than that 20 In the digit group 4 individual $_ts Beyond the value of , There are other places 7 Values are also used , Direct search can locate , this 7 Values are relatively simple , Every time it is fixed $_ts The inside number 2、3、4、15、16、17、19 The value of a , alike , Find the location , Dynamic replacement is enough :

20274abcb1d701297d3769adfb958303.png

matters needing attention

Particular attention VM The beginning of the code , Will directly call and execute some methods , The values of some variables are generated by these methods , When you follow step by step, you find that some parameters are wrong , Or not , Then you have to pay attention to these methods at the beginning , It may have been generated from the beginning .

464ebb139d670d56128b01a5d3eb687a.png

suffix MmEwMD Generative logic

Other follow-up XHR In request , With a suffix , The value of this suffix is also determined by JS Generated , It changes every time , Of course, different websites , The suffixes are not always the same , In this case, it is MmEwMD, Next XHR The breakpoint , When XHR The request contains MmEwMD= Cut off when , Then refresh the page :

89b2d26d035e3fbe120dc3fbe78f118e.png

You can see it and then pass it in l.open() Of URL It's still normal , When it is disconnected, it will arrive l.send() It has a suffix , Look again l.open() In fact, that is xhr.open(), Obviously different from normal , This method is also used VM In the code , It should be rewriting the method , It can be compared with normal :

1883564d53f4ffec5541259be8143d18.png

Follow me VM Look in the code , After _$sd(arguments[1]) Method becomes a complete link with suffix :

38b00db03e0a4fcc7ac1b285c9b20290.png

To follow up _$sd Method , The front is right url Do something about it , There is an entry at the back 779 No. 1 control flow , In fact, we generated Cookie Steps for , Just follow me .

e3f394e1ccfa558e87855a47685ebe9e.png

Make good use of Watch Tracking function

11ede2414a29b2bcccc6a6ebb9b01d17.png


Developer Tools Watch The function can continuously track the value of a variable , There are many cases of this control flow , Set the corresponding variable tracking , It can let you know which control flow you are in now , And the changes of the generated array , I don't know where to go .

The results verify that

If the whole process is ok , The code is also correct , Carry the right Cookie And the correct suffix , You can successfully visit :

83396494daf4f9b9af3648d740a273a9.png

80ac0608dee4f9729f0f08d606efa3b7.png

16e8171349d188d8be79a8431ee1f012.png

End

Cui Qingcai's new book 《Python3 Web crawler development practice ( The second edition )》 It's officially on the market ! The book details the use of zero basis Python Develop all aspects of reptile knowledge , At the same time, compared with the first edition, it has added JavaScript reverse 、Android reverse 、 Asynchronous crawler 、 Deep learning 、Kubernetes Related content ,‍ At the same time, this book has obtained Python The father of Guido The recommendation of , At present, this book is on sale at a 20% discount !

Content introduction :《Python3 Web crawler development practice ( The second edition )》 Content introduction

05639d7088bf3120ce22d3ce2c0bbfdc.jpeg

Scan purchase

159e0d3513f829e8e914f5e8af640028.png

a4b845770180b1efb2dab9c588bed1b9.png

You'd better watch it

56c96064ab9167e082f1db154bdd79ef.png

原网站

版权声明
本文为[VIP_ CQCRE]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/187/202207061542098837.html

随机推荐