赞
踩
3、js动态网页抓取方式(重点)
许多时候爬虫取到的页面仅仅是一个静态的页面,即网页的源代码,就像在浏览器上的“查看网页源代码”一样。
一些动态的东西如javascript脚本执行后所产生的信息是抓取不到的,下面两种方案,可用来python爬取js执行后输出的信息。
① 用dryscrape库动态抓取页面
js脚本是通过浏览器来执行并返回信息的,所以,抓取js执行后的页面,一个最直接的方式就是用python模拟浏览器的行为。
WebKit 是一个开源的浏览器引擎,python提供了许多库可以调用这个引擎,dryscrape便是其中之一,它调用webkit引擎来处理包含js等的网页。
import 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类似的框架还有一个windmill,感觉稍复杂一些,这里就暂且不赘述了。
4、解析js(重点)
我们爬虫每次只有一个请求,但是实际上很多请求又js连带发送,所以我们需要利用爬虫解析js去实现这些请求的发送。
网页中的参数来源主要有以下四种:
固定值, 写死在html中的参数
用户给的参数
服务器(通过ajax)返回的参数, 比如时间戳, token等
js生成的参数
这里主要介绍一下解析js,破解加密方法或者生成参数值方法,python代码模拟实现这个方法, 从而得到我们需要的请求参数。
以微博登录为例:
当我们点击登录的时候都会发送一个login请求
登录表单中的参数并不一定都是我们需要的,可以通过对比多次请求中的参数,再加上一些经验和猜想,过滤掉固定参数或服务器自带参数和用户输入的参数。
这是剩下的就是js生成的数值或加密数值;
最终得到的值:
pcid: yf-d0efa944bb243bddcf11906cda5a46dee9b8
su: cXdlcnRxd3Jl
nonce: 2SSH2A # 未知
sp: e121946ac9273faf9c63bc0fdc5d1f84e563a4064af16f635000e49cbb2976d73734b0a8c65a6537e2e728cd123e6a34a7723c940dd2aea902fb9e7c6196e3a15ec52607fd02d5e5a28e18254105358e897996f0b9057afe2d24b491bb12ba29db3265aef533c1b57905bf02c0cee0c546f4294b0cf73a553aa1f7faf9f835e5
prelt: 148 # 未知
请求参数中的用户名和密码都是经过加密处理的,如果需要模拟登录,就需要找到这个加密的方法,利用它来为我们的数据进行加密。
1)找到所需的js
要找到加密方法,首先我们需要先找到登录所需的js代码,可以使用以下3种方式:
① 找事件; 在页面检查目标元素,在开发工具的子窗口里选中Events Listeners, 找到click事件,点击定位到js代码。
② 找请求;在Network中点击列表界面的对应Initiator跳转至对应js界面;
③ 通过搜索参数名进行定位;
2)登录的js代码
3)在这个submit的方法上打断点,然后输入用户名密码,先不点登录,回到dev tool点击这个按钮启用调试。
4)然后再去点登录按钮, 这时候就可以开始调试;
5)逐步执行代码的同时观察我们输入的参数, 发生变化的地方即为加密方法, 如下
6)上图中的加密方式是base64, 我们可以使用代码来试一下
import base64
a = “aaaaaaaaaaaa” # 输入的用户名
print(base64.b64encode(a.encode())) # 得到的加密结果:b’YWFhYWFhYWFhYWFh’
得到的加密结果与网页上js的执行结果一致;
5、爬虫中遇到的js反爬技术(重点)
1)JS写cookie
requests请求得到的网页是一对JS,跟浏览器打开看到的网页源码完全不一样,这种情况,往往是浏览器运行这段JS生成一个(或多个)cookie再带着这个cookie做二次请求。
在浏览器(chrome、Firefox都可以)里可以看到这一过程,首先把Chrome浏览器保存的该网站的cookie删除,按F12到Network窗口,把“preserve log”选中(Firefox是“Persist logs”),刷新网页,这样我们就可以看到历史的Network请求记录。
第一次打开“index.html”页面时返回的是521, 内容是一段JS代码;
第二次请求这个页面就得到了正常的HTML,查看两次请求的cookies,可以发现第二次请求时带上了一个cookie,而这个cookie并不是第一次请求时服务器发过来的,其实它就是JS生成的。
解决思路:研究那段JS,找到它生成cookie的算法,爬虫就可以解决这个问题。
2)JS加密ajax请求参数
抓某个网页里面的数据,发现网页源代码里面没有我们要的数据,麻烦之处在于数据往往是ajax请求得到的。
按F12打开Network窗口,刷新网页看看加载这个网页都下载了哪些URL,我们要的数据就在某个URL请求的结果里面。
这类URL在Chrome的Network里面的类型大多是XHR,通过观察它们的“Response”就可以发现我们要的数据。
我们可以把这个URL拷贝到地址栏,把那个参数随便改个字母,访问一下看看是不是能得到正确的结果,由此来验证它是否是很重要的加密参数。
解决思路:对于这样的加密参数,可以尝试通过debug JS来找到对应的JS加密算法,其中关键的是在Chrome里面设置“XHR/fetch Breakpoints”。
3)JS反调试(反debug)
前面我们都用到了Chrome 的F12去查看网页加载的过程,或者是调试JS的运行过程。
不过这种方法用多了,网站就加了反调试的策略,只有我们打开F12,就会暂停在一个“debugger”代码行,无论怎样都跳不出去。
不管我们点击多少次继续运行,它一直在这个“debugger”这里,每次都会多出一个VMxx的标签,观察“Call Stack”发现它好像陷入了一个函数的递归调用。
这个“debugger”让我们无法调试JS,但是关掉F12窗口,网页就正常加载了。
解决思路:“反-反调试”,通过“Call Stack”找到把我们带入死循环的函数,重新定义它。
JS的运行应该停止在设置的断点处,此时该函数尚未运行,我们在Console里面重新定义它,继续运行就可以跳过该陷阱。
4)JS发送鼠标点击事件
有些网站它的反爬都不是上面的方式,你从浏览器可以打开正常的页面,而在requests里面却被要求输入验证码或重定向其它网页。
可以试着从“Network”看看,比如下面这个Network流里面的信息:
认真看看后会发现,每点击页面的的链接,它都会做一个“cl.gif”的请求,它看上去是下载一个gif图片,然而并不是。
它请求时发送的参数非常多,而且这些参数都是当前页面的信息。比如包含了被点击的链接等等。
先来顺一下它的逻辑:
JS会响应链接被点击的事件,在打开链接前,先访问cl.gif,把当前的信息发送给服务器,然后再打开被点击的链接。服务器收到被点击链接的请求,会看看之前是不是已经通过cl.gif把对应信息发过来,如果发过来了就认为是合法的浏览器访问,给出正常的网页内容。
因为requests没有鼠标事件响应就没有访问cl.gif的过程就直接访问链接,服务器就拒绝服务。
逻辑绕明白了就好办了!
解决思路:在访问链接前先访问一下cl.gif即可,关键是要研究cl.gif后的参数,把这些参数都带上问题就不大了,这样就可以绕过这个反爬策略。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。