动态网页抓取( Python爬虫入门基础资料、项目实战练习(一)|Python)

优采云 发布时间: 2021-12-23 10:06

  动态网页抓取(

Python爬虫入门基础资料、项目实战练习(一)|Python)

  var carname="Volvo";

  3) 变量命名规则

  ① 由字母、数字、下划线和$组成,但不能以数字开头。例如,名称 12asd 会报错

  ②不能是关键字或保留字,如var、for等。

  ③ 严格区分大小写,即大写和小写是不同的变量

  4)数据类型

  JavaScript 数据有两种类型,一种是简单数据类型,另一种是复杂数据类型。

  示例:返回类型为数字;

  

var a = 123; //var是设置一个变量

alert('hello') //一个弹窗,可以判断是否为外部引入的

console.log(a) //console.log():是在浏览器的控制台上的输出

console.log(typeof a); //typeof 判断是属于什么类型

  注意:严格区分大小写,否则会出错。

  说到数据类型,数据类型之间的交换是必不可少的。这与 js 和 python 非常相似。

  介绍几个功能:

  (1)Number() 将数据转换成数字类型,里面的参数就是你要改变类型的数据。

  (2)toString() String() 两种将数据转换为字符串类型的方法;

  区别 String() 可以将null 转换为“null” toString() 返回undefined;

  (3)Boolean() 将数据类型转换为布尔类型;

  bool 返回两种数据类型,一种为真,另一种为假。

  Boolean类型转换为Number时,true会转为1,false会转为0。该方法不支持将数字开头有其他字符的字符串转为数字类型,如"12df ”。

  2、Python中执行JS代码的三种方式

  方法一:使用js2py

  基本操作示例:

  import js2py

# 执行单行js语句

js2py.eval_js("console.log(abcd)")

>>> abcd

# 执行js函数

add = js2py.eval_js("function add(a, b) {return a + b};")

print(add(1,2))

>>> 3

# 另一种方式

js = js2py.EvalJs({})

js.execute("js语句")

  在js代码中引入python对象或python代码

  # 在js代码中引入python对象

context = js2py.EvalJs({'python_sum': sum})

context.eval('python_sum(new Array(1,4,2,7))')

>>> 14

# 在js代码中加入python代码

js_code = '''

var a = 10

function f(x) {return x*x}

'''

context.execute(js_code)

context.f("14") 或 context.f(14)

>>> 196

  将js代码转换为python模块,然后使用import导入

  # 转换js文件

js2py.translate_file('example.js', 'example.py')

# 现在可以导入example.py

from example import example

example.someFunction()

# 转换js代码

js2py.translate_js('var $ = 5')

>>>

"""

from js2py.pyjs import *

# setting scope

var = Scope( JS_BUILTINS )

set_global_object(var)

# Code follows:

var.registers(['$'])

var.put('$', Js(5.0))

"""

  但是py2js在加载一些加密函数的时候,有时候效率会很差,可能是因为执行机制不同;

  py2js直接调用的nodejs引擎,但是把这个库使用的nodejs解析语法树转换成了py代码。性能相当低。最好使用execjs直接调用nodejs或者自己封装子进程调用。

  方法二:使用execjs

  import execjs

js_code = open('file.js',encoding='utf-8').read()

ctx = execjs.compile(js_code)

# 第一个参数为ja代码中的函数名, 后面为函数对应的参数

result = ctx.call('function_name', *args)

  方法三:使用subprocess调用node子进程

  import subprocess

# js文件最后必须有输出,我使用的是 console.log

pro = subprocess.run("node abc.js", stdout=subprocess.PIPE)

# 获得标准输出

_token = pro.stdout

# 转一下格式

token = _token.decode().strip()

  这里也和大家分享一些我采集到的Python爬虫学习资源,入门基础资料,项目实战练习等等,有需要的进群找群管理获取↓↓

  

  3、js 动态网页爬取方法(重点)

  很多时候爬虫抓取的页面只是一个静态页面,也就是网页的源代码,就像在浏览器上“查看网页的源代码”一样。

  一些动态的东西比如javascript脚本执行后产生的信息是无法捕获的。下面两种方案可以用来爬取python执行js后输出的信息。

  ①使用dryscrape库动态抓取页面

  Node.js 脚本通过浏览器执行并返回信息。所以js执行后抓取页面最直接的方法之一就是用python模拟浏览器的行为。

  WebKit 是一个开源浏览器引擎。Python 提供了许多库来调用这个引擎。干刮就是其中之一。它调用webkit引擎来处理收录js等的网页。

   import dryscrape

# 使用dryscrape库 动态抓取页面

def get_url_dynamic(url):

session_req=dryscrape.Session()

session_req.visit(url) #请求页面

response=session_req.body() #网页的文本

#print(response)

return response

get_text_line(get_url_dynamic(url)) #将输出一条文本

  这也适用于其他收录js的网页。虽然可以满足抓取动态页面的要求,但是缺点还是很明显:慢!

  但仔细想想也是有道理的。Python调用webkit请求页面,页面加载完成后,加载js文件,让js执行,返回执行的页面。慢一点是合理的。

  另外,可以调用webkit的库还有很多:PythonWebkit、PyWebKitGit、Pygt(你可以用它来写浏览器)、pyjamas等,也可以实现同样的功能。

  ② selenium web 测试框架

  Selenium是一个Web测试框架,允许调用本地浏览器引擎发送网页请求,所以也可以实现抓取页面的要求。

  可以使用 selenium webdriver,但它会实时打开浏览器窗口。

   def get_url_dynamic2(url):

driver=webdriver.Firefox() #调用本地的火狐浏览器,Chrom 甚至 Ie 也可以的

driver.get(url) #请求页面,会打开一个浏览器窗口

html_text=driver.page_source

driver.quit()

#print html_text

return html_text

get_text_line(get_url_dynamic2(url)) #将输出一条文本

  这是一个临时解决方案。还有一个类似selenium的框架中的风车,感觉稍微复杂了一些,这里就不赘述了。

  4、解析js(重点)

  我们的爬虫一次只有一个请求,但实际上很多请求都是和js一起发送的,所以我们需要使用爬虫解析js来发送这些请求。

  网页中的参数来源主要有四种:

  这里主要介绍解析js的方法,破解加密的方法或者生成参数值的方法。python代码模拟了该方法的实现,从而获取到我们需要的请求参数。

  以微博登录为例:

  当我们点击登录时,我们会发送一个登录请求

  

  登录表单中的参数不一定是我们需要的全部。您可以通过比较多个请求中的参数,加上一些经验和推测,过滤掉固定参数或服务器输入的参数和用户输入的参数。

  这是js生成的值或加密值;

  最终值:

  # 图片 picture id:

pcid: yf-d0efa944bb243bddcf11906cda5a46dee9b8

# 用户名:

su: cXdlcnRxd3Jl

nonce: 2SSH2A # 未知

# 密码:

sp: e121946ac9273faf9c63bc0fdc5d1f84e563a4064af16f635000e49cbb2976d73734b0a8c65a6537e2e728cd123e6a34a7723c940dd2aea902fb9e7c6196e3a15ec52607fd02d5e5a28e18254105358e897996f0b9057afe2d24b491bb12ba29db3265aef533c1b57905bf02c0cee0c546f4294b0cf73a553aa1f7faf9f835e5

prelt: 148 # 未知

  请求参数中的用户名和密码是加密的。如果您需要模拟登录,您需要找到这种加密方法并使用它来加密我们的数据。

  1)找到需要的js

  要找到加密方法,我们首先需要找到登录所需的js代码,可以使用以下3种方法:

  ① 查找事件;查看页面上的目标元素,在开发工具的子窗口中选择Events Listeners,找到点击事件,点击定位到js代码。

  

  ② 查找请求;点击Network中列表界面对应的Initiator跳转到对应的js界面;

  

  ③通过搜索参数名称定位;

  

  2)登录js代码

  

  3) 在submit方法上打断,然后输入用户名和密码,不用登录,回到开发工具,点击这个按钮开启调试。

  

  4) 然后去登录按钮,就可以开始调试了;

  5)在一步步执行代码的同时,观察我们输入的参数。发生变化的地方是加密方式,如下

  

  6)上图中的加密方式是base64,我们可以用代码试试

  import base64

a = "aaaaaaaaaaaa" # 输入的用户名

print(base64.b64encode(a.encode())) # 得到的加密结果:b'YWFhYWFhYWFhYWFh'

# 如果用户名包含@等特殊符号, 需要先用parse.quote()进行转义

  得到的加密结果和js在网页上的执行结果一致;

  5、 爬虫遇到的js反爬技术(重点)

  1)JS 写 cookie

  requests得到的网页是一对JS,与浏览器打开的网页源码完全不同。在这种情况下,浏览器运行这个 JS 来生成一个(或多个)cookie,然后第二次获取这个 cookie。要求。

  这个过程可以在浏览器(chrome 或 Firefox)中看到。首先删除Chrome浏览器中保存的网站 cookie,按F12到网络窗口,选择“保留日志”(Firefox为“持久日志”),刷新网页,这样我们就可以看到历史记录了网络请求记录。

  

  “index.html”页面第一次打开时,返回521,内容为一段JS代码;

  当我第二次请求这个页面时,我得到了正常的 HTML。查看两次请求的cookies,可以发现第二次请求中携带了一个cookie,而这个cookie在第一次请求时没有被服务器发送。其实就是JS生成的。

  解决方法:研究JS,找到生成cookie的算法,爬虫可以解决这个问题。

  2)JS加密的ajax请求参数

  抓取某个网页中的数据,发现该网页的源代码中没有我们想要的数据。麻烦的是,数据往往是通过ajax请求获取的。

  按F12打开网络窗口,刷新网页,看看加载这个网页后下载了哪些网址,我们要的数据在一个网址请求的结果中。

  Chrome 的 Network 中这类 URL 的类型多为 XHR,我们想要的数据可以通过观察它们的“Response”来找到。

  我们可以把这个URL复制到地址栏,把那个参数改成任意一个字母,然后访问看看能不能得到正确的结果,从而验证它是否是一个重要的加密参数。

  解决方法:对于此类加密参数,可以尝试通过调试JS找到对应的JS加密算法。关键是在Chrome中设置“XHR/fetch Breakpoints”。

  

  3)JS 反调试(anti-debug)

  之前我们都是用Chrome的F12来查看网页加载的过程,或者调试JS的运行过程。

  不过这个方法用的太多了,网站加了反调试策略。只有当我们打开 F12 时,它才会在“调试器”代码行处暂停,无论如何它不会跳出。

  

  不管我们点击多少次继续运行,它总是在这个“调试器”里,每次都会多出一个VMxx标签,观察“调用栈”发现好像卡在了一个递归调用一个函数。

  这个“调试器”阻止我们调试JS,但是关闭F12窗口,网页加载正常。

  解决办法:“反反调试”,通过“调用栈”找到让我们陷入死循环的函数,重新定义。

  JS 的运行应该在设置的断点处停止。此时,该功能尚未运行。我们在 Console 中重新定义它并继续运行以跳过陷阱。

  4)JS 发送鼠标点击事件

  一些网站它的反爬虫不是上面的方法,你可以从浏览器打开一个正常的页面,但是在请求中,你被要求输入验证码或重定向到其他网页。

  您可以尝试查看“网络”,例如网络流中的以下信息:

  

  仔细看,你会发现每次点击页面上的链接,都会发出“cl.gif”的请求。看起来它正在下载 gif 图片,但事实并非如此。

  它在请求时发送了很多参数,这些参数就是当前页面的信息。例如,它收录点击的链接等。

  首先,让我们遵循它的逻辑:

  JS 会响应链接被点击的事件。打开链接前,先访问cl.gif,将当前信息发送到服务器,然后打开点击的链接。服务器接收到点击链接的请求,会检查之前是否通过cl.gif发送过相应的信息。如果发送,将被视为合法的浏览器访问,并提供正常的网页内容。

  因为请求没有响应鼠标事件,所以没有访问cl.gif进程直接访问链接,服务器拒绝服务。

  如果你理解它,很容易处理逻辑!

  解决方案:只需在访问链接之前访问 cl.gif。关键是研究cl.gif之后的参数。把这些参数放在一起不是什么大问题,所以可以绕过这个防爬策略。

  今天的爬虫分享到此结束~更多Python爬虫学习干货和学习资源欢迎加入下方Python学习技术交流群。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线