浏览器抓取网页(python爬取js动态网页抓取方式(重点)(重点))
优采云 发布时间: 2022-03-24 23:09浏览器抓取网页(python爬取js动态网页抓取方式(重点)(重点))
3、js动态网页爬取方法(重点)
很多情况下,爬虫检索到的页面只是一个静态页面,也就是网页的源代码,就像在浏览器上“查看网页源代码”一样。
一些动态的东西,比如javascript脚本执行后产生的信息,是无法捕捉到的。下面两种方案可以用于python爬取js执行后输出的信息。
① 使用dryscrape库动态抓取页面
js脚本由浏览器执行并返回信息。因此,在js执行后捕获页面最直接的方法之一就是使用python来模拟浏览器的行为。
WebKit是一个开源的浏览器引擎,python提供了很多库来调用这个引擎,dryscrape就是其中之一,它调用webkit引擎来处理收录js等的网页。
*敏*感*词*干刮
使用 dryscrape 库动态抓取页面
def get_url_dynamic(url):
session_req=dryscrape.Session()
session_req.visit(url) #请求页面
response=session_req.body() #网页文本
#打印(响应)
返回响应
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() #调用本地Firefox浏览器,Chrom甚至Ie也可以
driver.get(url) #请求一个页面,会打开一个浏览器窗口
html_text=driver.page_source
driver.quit()
#打印html_text
返回 html_text
get_text_line(get_url_dynamic2(url)) # 将输出一个文本
可以看作是治标不治本。类似selenium的框架也有风车,感觉稍微复杂一些,这里就不赘述了。
4、解析js(强调)
我们的爬虫每次只有一个请求,但实际上很多请求是和js一起发送的,所以我们需要使用爬虫解析js来实现这些请求的发送。
网页中的参数主要有四种来源:
固定值,html写的参数
用户给定的参数
服务器返回的参数(通过ajax),例如时间戳、token等。
js生成参数
这里主要介绍解析js、破解加密方式或者生成参数值的方法。python代码模拟这个方法来获取我们需要的请求参数。
以微博登录为例:
当我们点击登录时,我们会发送一个登录请求
登录表单中的参数不一定是我们所需要的。通过比较多个请求中的参数,再加上一些经验和猜测,我们可以过滤掉固定参数或者服务器自带的参数和用户输入的参数。
这是js生成的剩余值或加密值;
得到的最终值:
图片图片编号:
pcid: yf-d0efa944bb243bddcf11906cda5a46dee9b8
用户名:
苏:cXdlcnRxd3Jl
随机数:2SSH2A #未知
密码:
SP:e121946ac9273faf9c63bc0fdc5d1f84e563a4064af16f635000e49cbb2976d73734b0a8c65a6537e2e728cd123e6a34a7723c940dd2aea902fb9e7c6196e3a15ec52607fd02d5e5a28ee897996f0b9057afe2d24b491bb12ba29db3265aef533c1b57905bf02c0cee0c546f4294b0cf73a553aa1f7faf9f835e5
prelt: 148 # 未知
请求参数中的用户名和密码是加密的。如果需要模拟登录,就需要找到这种加密方式,用它来加密我们的数据。
1)找到需要的js
要找到加密方法,首先我们需要找到登录所需的js代码,我们可以使用以下3种方法:
① 查找事件;在页面中查看目标元素,在开发工具的子窗口中选择Events Listeners,找到点击事件,点击定位到js代码。
② 查找请求;在Network中的列表界面点击对应的Initiator,跳转到对应的js界面;
③ 通过搜索参数名称定位;
2)登录js代码
3)在这个提交方法上断点,然后输入用户名和密码,先不要登录,回到开发工具点击这个按钮开启调试。
4)然后点击登录按钮,就可以开始调试了;
5)一边一步步执行代码,一边观察我们输入的参数。变化的地方是加密方式,如下
6)上图中的加密方式是base64,我们可以用代码试试
导入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到Network窗口,选择“preserve log”(Firefox是“Persist logs"),刷新网页,可以看到历史网络请求记录。
第一次打开“index.html”页面时,返回521,内容为一段JS代码;
第二次请求此页面时,您将获得正常的 HTML。查看这两个请求的cookie,可以发现第二个请求中带了一个cookie,而这个cookie并不是第一个请求时服务器发送的。其实它是由JS生成的。
解决方法:研究JS,找到生成cookie的算法,爬虫可以解决这个问题。
2)JS加密ajax请求参数
抓取某个网页中的数据,发现该网页的源码中没有我们想要的数据。麻烦的是,数据往往是通过ajax请求获取的。
按F12打开Network窗口,刷新网页看看加载这个网页的时候已经下载了哪些URL,我们要的数据在一个URL请求的结果中。
Chrome 的 Network 中的这些 URL 大部分都是 XHR,我们可以通过观察它们的“Response”来找到我们想要的数据。
我们可以把这个URL复制到地址栏,把参数改成任意字母,访问看看能不能得到正确的结果,从而验证它是否是一个重要的加密参数。
解决方法:对于这样的加密参数,可以尝试通过debug JS找到对应的JS加密算法。关键是在 Chrome 中设置“XHR/fetch Breakpoints”。
3)JS反调试(反调试)
之前大家都是用Chrome的F12来查看网页加载的过程,或者调试JS的运行过程。
不过这个方法用的太多了,网站增加了反调试策略。只要我们打开F12,它就会停在一个“调试器”代码行,无论如何也不会跳出来。
无论我们点击多少次继续运行,它总是在这个“调试器”中,而且每次都会多出一个VMxx标签,观察“调用栈”发现似乎陷入了递归函数调用.
这个“调试器”让我们无法调试JS,但是当F12窗口关闭时,网页正常加载。
解决方法:“反反调试”,通过“调用栈”找到让我们陷入死循环的函数,重新定义。
JS 的运行应该在设置的断点处停止。此时,该功能尚未运行。我们在Console中重新定义,继续运行跳过陷阱。
4)JS 发送鼠标点击事件
有的网站它的反爬不是上面的方法,可以从浏览器打开正常的页面,但是requests中会要求你输入验证码或者重定向其他网页。
您可以尝试从“网络”中查看,例如以下网络流中的信息:
仔细一看,你会发现每次点击页面上的链接,都会发出一个“cl.gif”请求,看起来是下载gif图片,其实不是。
它在请求的时候会发送很多参数,这些参数就是当前页面的信息。例如,它收录点击的链接等。
我们先按照它的逻辑:
JS 会响应链接被点击的事件。在打开链接之前,它会先访问cl.gif,将当前信息发送到服务器,然后再打开点击的链接。当服务器收到点击链接的请求时,会检查之前是否通过cl.gif发送过相应的信息。
因为请求没有鼠标事件响应,所以直接访问链接,没有访问cl.gif的过程,服务器拒绝服务。
很容易理解其中的逻辑!
解决方案:在访问链接之前访问 cl.gif。关键是研究cl.gif后的参数。带上这些参数问题不大,这样就可以绕过这个反爬策略了。