转载请注明出处:http://www.cnblogs.com/codefish/p/4993809.html
最近在群里频繁的被问到ajax和js的处理问题,我们都知道,现在很多的页面都是用动态加载的技术,这一方面带来了良好的页面体验,另一方面,在抓取时或者或少的带来了相当大的麻烦,因为我们知道直接get主页页面url,这些内容是没有办法显示的。那怎么处理这些内容呢?
上图是一个直观的分析,在抓取数据时,我们一般优先考虑到手机端的网站,因为手机端的网站得到数据相对容易,特别是wap协议的网站,其分页方式大多不是ajax分页或者瀑布流的形式,所以抓取相对容易的多。另外在分析到请求头之后,我们可以很方便得到ajax请求地址,这个时候直观的去call这个地址,看能否正常的得到的数据。换了浏览器然后在call一次,看数据能否正常,如果正常,那个url可能就是public的,那在保障一定的频率访问之后就可以很容易的拿到数据。下面我用一个例子来说明分析请求的。
打开目标网站,查看加载方式:
https://www.abdserotec.com/primary-antibodies-monoclonal-polyclonal.html#productType=Monoclonal%20Antibody
分析网站
当我打开网站的时候,可以很明显的发现数据是通过下拉列表,到底端之后解发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]]
那我直接在浏览器打开看看:
很显然的看到了熟悉的json格式的字符串
别急,这里我们需要更换浏览器打开刚刚的api接口,为什么要这样做?因为我们现在打开的时候都会带上了一定的请求参数,我们更换浏览器就是清掉这些参数,然后再来访问,如果还是得到数据,这样说明这个api接口本身就是public的,而且管理员对这个接口没有做filter 。
进一步分析参数
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 写了一个简单的脚本:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
__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, ':', |
另外,朋友说如何得到总页数呢?我们假定以现有的40页的数据量,假定总页数为100,如果第100页有数据,那访问第200页,如果没有得到数据,那访问第(100+200)/2页数据,依此类推,差不多log2N次就可以得到总页数,这里就用二分法就可以得到。
题外话
教程是死的,人是活的,当你拿到类似的api之后,再请求的时候请务必带上请求参数,然后在模拟请求,因为每个api对于特定的参数才有返回行为,比如以下留言的某个朋友的接口
http://www.sse.com.cn/assortment/stock/list/share/
代码:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
# -*- coding: utf-8 -*- import requests def get_page(): url = 'http://query.sse.com.cn/security/stock/getStockListData2.do?&jsonCallBack=jsonpCallback63221&isPagination=true&stockCode=&csrcCode=&areaName=&stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=1&pageHelp.pageSize=25&pageHelp.pageNo=1&_=1483604495929' headers = { 'Accept': '*/*', 'Accept-Encoding': 'gzip, deflate, sdch', 'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6', 'Cache-Control': 'no-cache', 'Connection': 'keep-alive', 'Cookie': 'yfx_c_g_u_id_10000042=_ck17010516212811073361827608343; yfx_f_l_v_t_10000042=f_t_1483604488100__r_t_1483604488100__v_t_1483604488100__r_c_0; VISITED_MENU=%5B%228528%22%5D', 'Host': 'query.sse.com.cn', 'Pragma': 'no-cache', 'Referer': 'http://www.sse.com.cn/assortment/stock/list/share/', 'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36', } print(requests.get(url=url, headers=headers).text) if __name__ == '__main__': get_page() |
写代码呢,纯粹的乐趣,毕竟分享的事儿,有问题大可以留言,不过责怪我这没有做全套,帮你代码写完还要调试给你,这就没劲对吧,毕竟我没拿你一分利,顶多提供思路,大家都这么忙
总结
本次文章主要分析ajax可以直接调用和分析请求的过程,在我看来,码代码通过思考来分析问题,比硬写代码死磕来的强的多,下次我将分析一下直接call ajax接口没办法解决的情况.
我爬的这个网站http://www.sse.com.cn/assortment/stock/list/share/找不到你所说的这种json 连接,
http://query.sse.com.cn/security/stock/getStockListData2.do?&jsonCallBack=jsonpCallback94564&isPagination=true&stockCode=&csrcCode=&areaName=&stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=2&pageHelp.pageSize=25&pageHelp.pageNo=2&pageHelp.endPage=21&_=147969315111
这个url在浏览器地址栏里你确定能请求到数据?
# -*- coding: utf-8 -*-import requestsdef get_page(): url = 'http://query.sse.com.cn/security/stock/getStockListData2.do?&jsonCallBack=jsonpCallback63221&isPagination=true&stockCode=&csrcCode=&areaName=&stockType=1&pageHelp.cacheSize=1&pageHelp.beginPage=1&pageHelp.pageSize=25&pageHelp.pageNo=1&_=1483604495929' headers = { 'Accept':'*/*', 'Accept-Encoding':'gzip, deflate, sdch', 'Accept-Language':'zh-CN,zh;q=0.8,en;q=0.6', 'Cache-Control':'no-cache', 'Connection':'keep-alive', 'Cookie':'yfx_c_g_u_id_10000042=_ck17010516212811073361827608343; yfx_f_l_v_t_10000042=f_t_1483604488100__r_t_1483604488100__v_t_1483604488100__r_c_0; VISITED_MENU=%5B%228528%22%5D', 'Host':'query.sse.com.cn', 'Pragma':'no-cache', 'Referer':'http://www.sse.com.cn/assortment/stock/list/share/', 'User-Agent':'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36', } print(requests.get(url=url,headers=headers).text)if __name__ == '__main__': get_page()请问你有什么不确定的吗?
那你写清楚啊,贴一段代码,导致我们断章取义,调试了半天也没有效果
我有说这个在浏览器里面打的开吗? 你难道不懂自按照教程把所有参数都填上去然后模拟请求?连基本的常识都没有还好意思怪别人教程不清晰,要不然你我帮你代码写好了调试说清楚了好不好?
自己多思考,多实践。
你好。你这个博客系统是开源的吗?什么语言实现。我也想搭一个
你好,这个就是wordpress,皮肤是自己在网上找了自己改了一下。
好的谢谢!
博主,请教一下,请看一下链接里的图:http://pan.baidu.com/s/1jIsOPKU--urlhttp://pan.baidu.com/s/1kUCjrHd ----页面原图http://pan.baidu.com/s/1gfuWKSj---源码截图1http://pan.baidu.com/s/1miK5dnq---源码截图2这是我想要爬取的数据页,但json格式的字符串中只有字段名称,没有具体数据。请问能否给个提示和思路? 或者这种的网页是不能爬的?
数据应该是在其它的地方传输出来的,要多分析,另外,只要是web浏览器能打开,基本都能爬
博主你好,多谢你的分享。我现在碰到个问题不知能否麻烦帮我看看:http://www.itslaw.com/sh这个网站,我找到了api之后但是打不开(1.我找到的地址是“http://www.itslaw.com/api/v1/caseFiles?startIndex=0&countPerPage=20&sortType=1&conditions=region%2BB%2B1%2B%E6%B5%99%E6%B1%9F%E7%9C%81” 2.在你的博文中对应的应该是“我们得到请求地址了:”、‘“那我直接在浏览器打开看看:”这一块,但是我这个地址怎么也打不开),能不能抽空帮我看看?多谢了!
哦对了,上面我说的打不开,不光是浏览器中url打不开,在python加上所有的headers之后还是没有数据返回,按照我粗浅的经验来看,此时应有json返回,我懵了。。
# -*- coding: utf-8 -*-
import requests
def get_content():
url = 'http://www.itslaw.com/api/v1/caseFiles?startIndex=0&countPerPage=20&sortType=1&conditions=searchWord%2B%E4%B8%AD%E5%9B%BD%2B1%2B%E4%B8%AD%E5%9B%BD'
headers = {
'Accept': 'application/json, text/plain, */*',
'Accept-Encoding': 'gzip, deflate, sdch',
'Accept-Language': 'zh-CN,zh;q=0.8,en;q=0.6',
'Cache-Control': 'no-cache',
'Cookie': 'Hm_lvt_e496ad63f9a0581b5e13ab0975484c5c=1493866070; Hm_lpvt_e496ad63f9a0581b5e13ab0975484c5c=1493866070; gr_user_id=db90130e-d181-4919-9f03-5d4c7a5c679b; gr_session_id_8d9004219d790ea8=985a9e4f-6b1d-4418-b048-47d59118755f; sessionId=feebbfc9-d728-4cb5-b151-64c60b271367; subSiteCode=sh; showSubSiteTip=false',
'Host': 'www.itslaw.com',
'Pragma': 'no-cache',
'Referer': 'http://www.itslaw.com/search?searchMode=judgements&sortType=1&conditions=searchWord%2B%E4%B8%AD%E5%9B%BD%2B1%2B%E4%B8%AD%E5%9B%BD',
'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36',
}
r = requests.get(url=url, headers=headers)
print r.text
if __name__ == '__main__':
get_content()
请问这个代码你那边能出结果吗?我这里操作完没有结果返回。
返回内容太长,选一部分:
{"result":{"code":0,"message":"成功"},"data":{"searchResult":{"totalCount":4406261,"judgements":[{"id":"e06a367e-f2a0-4e7b-987b-e8cf7e6eb099","title":"指导案例78号:北京奇虎科技有限公司诉腾讯科技(深圳)有限公司、深圳市腾讯计算机系统有限公司滥用市场支配地位纠纷案","caseType":"民事","trialRound":"4","judgementType":"判决","courtName":"最高人民法院","caseNumber":"(2013)民三终字第4号","judgementDate":"2014-10-08","courtOpinion":"法.....
我真懵了,我这边不执行。。请问能联系你吗?能不能教教我
- - 代码和结果都贴给你了,还不能运行我也无能为力了。
请问从https://products.avnet.com/shop/SearchDisplay?searchTerm=MAX764CSA+&storeId=10151网页中拿取到第二个器件的地址,怎么样咯思路?
分析请求,如果分析不了就直接渲染
可以谈谈网站跨域攻击 或者蜜罐 这个对爬虫有影响
这个太宽了,属于网络安全的范围了,本主题只涵盖工程的部分,感谢你的意见