(9)分布式下的爬虫Scrapy应该怎么做-关于ajax抓取的处理(一)

(9)分布式下的爬虫Scrapy应该如何做-关于ajax抓取的处理(一)

转载请注明出处:http://www.cnblogs.com/codefish/p/4993809.html

  

最近在群里频繁的被问到ajax和js的处理问题,我们都知道,现在很多的页面都是用动态加载的技术,这一方面带来了良好的页面体验,另一方面,在抓取时或者或少的带来了相当大的麻烦,因为我们知道直接get主页页面url,这些内容是没有办法显示的。那怎么处理这些内容呢?

(9)分布式下的爬虫Scrapy应该怎么做-关于ajax抓取的处理(一)

 

上图是一个直观的分析,在抓取数据时,我们一般优先考虑到手机端的网站,因为手机端的网站得到数据相对容易,特别是wap协议的网站,其分页方式大多不是ajax分页或者瀑布流的形式,所以抓取相对容易的多。另外在分析到请求头之后,我们可以很方便得到ajax请求地址,这个时候直观的去call这个地址,看能否正常的得到的数据。换了浏览器然后在call一次,看数据能否正常,如果正常,那个url可能就是public的,那在保障一定的频率访问之后就可以很容易的拿到数据。下面我用一个例子来说明分析请求的。

 

 

一,打开目标网站,查看加载方式:

https://www.abdserotec.com/primary-antibodies-monoclonal-polyclonal.html#productType=Monoclonal%20Antibody

(9)分布式下的爬虫Scrapy应该怎么做-关于ajax抓取的处理(一)

 

二,分析网站

当我打开网站的时候,可以很明显的发现数据是通过下拉列表,到底端之后解发ajax事件来请求数据的,那我们实际的去他在请求的时候都发生了哪些事情

(9)分布式下的爬虫Scrapy应该怎么做-关于ajax抓取的处理(一)

 

我们得到请求地址了:

https://api.uk-plc.net/product_tables/v1/abd?filter={%22productType%22:{%22$in%22:[%22Monoclonal%20Antibody%22]}}&skip=360&limit=40&sort=[[%22specificitySummary%22,1],[%22host%22,1],[%22uniqueName%22,1],[%22format%22,1]]

 

那我直接在浏览器打开看看:

(9)分布式下的爬虫Scrapy应该怎么做-关于ajax抓取的处理(一)

 

很显然的看到了熟悉的json格式的字符串

 

别急,这里我们需要更换浏览器打开刚刚的api接口,为什么要这样做?因为我们现在打开的时候都会带上了一定的请求参数,我们更换浏览器就是清掉这些参数,然后再来访问,如果还是得到数据,这样说明这个api接口本身就是public的,而且管理员对这个接口没有做filter 。

(9)分布式下的爬虫Scrapy应该怎么做-关于ajax抓取的处理(一)

 

三,进一步分析参数

OK,这直接说明了可以直接访问这个接口,那如何分页呢?

我们来看URL里面都有哪些参数:

https://api.uk-plc.net/product_tables/v1/abd?filter={%22productType%22:{%22$in%22:[%22Monoclonal%20Antibody%22]}}&skip=360&limit=40&sort=[[%22specificitySummary%22,1],[%22host%22,1],[%22uniqueName%22,1],[%22format%22,1]]

 

skip=360

limit=40

这和C# linq的分页的方式何其的相似, 那我可以这样大胆假设一下:

limit 就是pagecount,每页的数量

skip就是略过第几页的数据

 

pageindex 第几页

 

那相应的取得几页的数据就是:

skip =(pageindex-1)*pagecount

limit = 40 

验证一下,数据还是得到

 

四,写代码

这里面我用python 写了一个简单的脚本:

__author__ = 'Bruce'
import requests

page_count = 20
page_index = 1
url_template = 'https://api.uk-plc.net/product_tables/v1/abd?filter={%22productType%22:{%22$in%22:[%22Monoclonal%20Antibody%22,%22Polyclonal%20Antibody%22]}}&skip={page_index}&limit={page_count}&sort=[[%22specificitySummary%22,1],[%22host%22,1],[%22uniqueName%22,1],[%22format%22,1]]'


def get_json_from_url(url):
    r = requests.get(url)
    return r.json()['results']


def init_url_by_parms(page_count=40, page_index=1):
    if not page_count or not page_index:
        return ''
    return url_template.replace('{page_index}', str((page_index - 1) * page_count)).replace('{page_count}',
                                                                                            str(page_count))


if __name__ == '__main__':
    url = init_url_by_parms(page_count=page_count, page_index=page_index)
    print url
    objs = get_json_from_url(url)
    if objs:
        for obj in objs:
            print '####################################'
            for k, v in obj.items():
                print k, ':', v

 

另外,朋友说如何得到总页数呢?我们假定以现有的40页的数据量,假定总页数为100,如果第100页有数据,那访问第200页,如果没有得到数据,那访问第(100+200)/2页数据,依此类推,差不多log2N次就可以得到总页数,这里就用二分法就可以得到。

 

总结:

本次文章主要分析ajax可以直接调用和分析请求的过程,在我看来,码代码通过思考来分析问题,比硬写代码死磕来的强的多,下次我将分析一下直接call ajax接口没办法解决的情况.

 转载请注意出处:http://www.cnblogs.com/codefish/p/4993809.html

3楼xgqfrms
Cookie 已经out 了;,在html5 的时代,我们可以使用webstorage;localstorage;indexDB;,来实现以上session,以及其他client 所需内容的存储;
Re: 爱吃猫的鱼
@xgqfrms,,cookie在短期内不会失效,至少短期内不会,现在但凡的网站很少有不去涉及cookie的方法,不知道你说out指的是啥
2楼tangqichao
Re: 爱吃猫的鱼
@tangqichao,引用赞,,thanks:)
1楼落幕残情
貌似动态网站,抓取步骤:,1.获取主界面HTML源码(/../..index.html),2.分析HTML页面所有JS 并把所有JS文件缓存到本地。,3.分析哪些JS文件是静态的。 静态JS永久缓存。,4.使用浏览器引擎解析HTML页面包括JS文件。,,LZ:这是本人的采集经验 欢迎吐槽
Re: 爱吃猫的鱼
@落幕残情,引用貌似动态网站,抓取步骤:,1.获取主界面HTML源码(/../..index.html),2.分析HTML页面所有JS 并把所有JS文件缓存到本地。,3.分析哪些JS文件是静态的。 静态JS永久缓存。,4.使用浏览器引擎解析HTML页面包括JS文件。,,LZ:这是本人的采集经验 欢迎吐槽,,,用浏览器去渲染js会有一个效率的问题,如果直接能得到接口将数据拉回来这样方法更高效一点,兄台做数据抓取也经验丰富呀。