Python反爬之破解动态页面(一)

前言

可能很多同学看到关于动态页面的反爬(比如基于Ajax的网页)第一反应就是selenium+headless browser,这个方法好是好,然而是基于真实的浏览器,虽然没有界面,但是也占用很多内存。小型的测试用selenium的确不错,但是一旦业务量大起来了,需求复杂了,甚至需要分布式爬虫操作时,这个方法对于内存的开销实在受不了。

那么有不用selenium的方法吗?当然有,今天就教大家硬刚基于Ajax的动态页面,从js的源码里边分析,一步一步倒推出页面的产生过程,从而获取我们所需要爬取的元素。

正文

一般来说,页面产生内容有以下几种方式:

  • 数据在页面内的js里边,由脚本动态渲染。直接右键查看源码搜索就能看到。
  • 数据在其他的js文件里边,由脚本动态渲染。需要找到哪个js包含这些数据。
  • 数据由Ajax生成,动态渲染。查看哪个XHR包含这些数据。
  • 数据由jsonp生成,动态渲染。查看哪个Script包含这些数据。

Python反爬之破解动态页面(一)_第1张图片

现在我们来分析一个网站。http://pubs.rsc.org/。这是一个关于化学的论文期刊数据库网站,可以通过关键字搜索论文或者书籍等。

Python反爬之破解动态页面(一)_第2张图片

我们通过关键字搜索bupt,可以看到出现了31条结果。

Python反爬之破解动态页面(一)_第3张图片

现在的需求是抓取文章列表,我们满怀信心右键一下查看源码,ctrl+f查找文章标题开头“The fate of”,然而,我们遗憾地发现,找到了0个结果。

Python反爬之破解动态页面(一)_第4张图片

于是我们f12一下,通过network查看一下,注意,最开始我们是不知道数据到底是怎么动态生成的,于是在xhr和Script里边都找一遍。经过一番尝试,我们确定了数据是有Ajax动态生成的,在XHR里边找到了我们所需要的内容。

Python反爬之破解动态页面(一)_第5张图片

哈!这不就是我们所需要的标题吗。于是开开心心的复制这个journalresult的url打开一看:

Python反爬之破解动态页面(一)_第6张图片

别急,再仔细看看journalresult的header才发现这是一个post请求获得的页面,我们没传参数当然看不到正确页面。

Python反爬之破解动态页面(一)_第7张图片

于是,问题又来了,Form Data里边,resultcount,category,pageno都还好说,这个searchterm一大堆是啥呀。看起来毫无规律,真叫人头大。

Python反爬之破解动态页面(一)_第8张图片

这个时候复制一下前面的一小段,‘AAEAAAD/////AQAAAAAAAAA’,准备到source里边find一下。结果,一下子就在原始html里边找到了。对比一下,一毛一样。至此,post所属的数据也有了。

Python反爬之破解动态页面(一)_第9张图片

我们回头分析整理一下,整个流程是这样:

  • get方法发送请求,url带上搜索的keyword。
  • 解析返回页面,获取接下来所需的searchterm和resultcount。
  • post方法向api发送请求,数据为刚刚获取的searchterm和resultcount。
  • 解析返回的页面,获取文章列表。
  • 处理文章列表,比如存入数据库或者写入文件等。

博主只展示前4步,第5步就很常规了,请大家自由发挥,以下是代码:

# -*- coding: utf-8 -*-
# @Author: Nessaj
# @Date:   2018-04-11 22:33:57
# @Last Modified by:   Nessaj
# @Last Modified time: 2018-04-12 22:34:14


import requests
import re
class pubulishing(object):
    """docstring for pubulishing"""
    def __init__(self,kw,page):

        self.baseurl = 'http://pubs.rsc.org/en/results?searchtext='
        self.kw = kw
        self.api = "http://pubs.rsc.org/en/search/journalresult"
        self.headers = {
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/65.0.3325.181 Safari/537.36'
        }
        self.page = page
    def get_SearchTerm_resultcount(self):

        url = self.baseurl + "{0}".format(self.kw)
        response = requests.get(url=url,headers=self.headers)
        content = response.text
        searchterm = re.search(r'\s*(.+?)\s*')
        artical_list = re.findall(pat,content)
        true_list=[]
        # 文章标题有些格式是用html标签完成的,比如氧气O2的下角标2,这里统一处理掉
        for each in artical_list:
            each = each.replace('','')
            each = each.replace('','')
            each = each.replace('','')
            each = each.replace('','')
            each = each.replace('','')
            each = each.replace('','')
            each = true_list.append(each)
        return true_list


pub=pubulishing('bupt',1)

artical_list = pub.get_artical_list()
print(artical_list)

输出是一个列表,如下图,由于是外网访问速度不是很稳定,所以用了4.7s,但是肯定比selenium的方法要快的:

Python反爬之破解动态页面(一)_第10张图片

后记

这是系列文章第一篇,算是一个比较简单的动态网页解析思路过程,都看到这里了,不给个赞嘛~后续还会有破解复杂的加密算法Ajax请求的分析,敬请期待。

代码已上传gtihub,欢迎大家来吐槽,觉得有意思的可以star一下啦

你可能感兴趣的:(python,爬虫,反爬虫)