python爬虫一(jupyter使用,ajax动态加载)

开发环境介绍

-----anaconda:
基于 数据分析和机器学习的集成环境(IDE)
-----jupyter:
anaconda提供的一个基于浏览器的可视化开发工具,可以把jupyter看成是anaconda的人性化版,就是为了方便开发者使用anaconda,如下图:

jupyter的基本使用

下载一个集成python的anaconda安装包即可,这里边内置了jupyter,输入jupyter notebook指令(安装anaconda时会自动键入环境变量)即可启动jupyter可视化的开发工具,相当于现在可以在127.0.0.1:8888这个网站里开发。然后再cd到xxx目录新建python3文件或者其他四种格式。
在这里插入图片描述

爬虫的三种分类:

1、通用爬虫:抓取整张页面源码。(一切爬虫的开始)

2、聚焦爬虫:抓取局部的数据(数据解析),聚焦爬虫是基于通用爬虫的。它才是我们的核心。

3、增量式爬虫:只爬最新更新的数据(或者说最新的url),这个肯定是要存一份上一次爬过的url来做对比的。

4、异步多任务爬虫:爬虫最头疼的就是网络请求,同步的概念是,发一个请求,就要等着远程服务器给响应,不给就一直等。而异步爬虫是,遇io等待则切换,用多线程或协程实现 ,用多进程浪费资源(计算类型,或没有io时间才用多进程)。

5、分布式爬虫:用scrapy-redis加redis来实现,多台机同时跑一摸一样的代码并且可以分担且不重复地(调度器去重)爬取海量url的数据

补充:

像爬虫这种io密集型,多线程可以,协程也要的。但最好用协程(微线程,最轻量且最快),其实我们用python3.4后引入的asyncio内置模块就能实现异步协程抓取。后面会讲到,实现代码也不复杂。但后面有了Scrapy(异步抓取框架),即人家帮我们实现好了异步代码(基于多线程的),我们只需要使用框架就行了,有了asyncio和Scrapy两种方法实现了异步,就够快了,但有人还嫌不够快,他说再快也是一台机在跑,所以分布式就是多台机都跑异步(用scrapy框架或手写asyncio异步)代码,就更快了,前面是一台机抓1000个url,现在是多台机抓1000个url。

开篇肯定是讲爬虫的robots协议,下图是京东的robots协议,要是按照这个,我们啥也爬不了,所以道理谁都懂。
在这里插入图片描述
写爬虫,不要定死请求参数,尽量把参数动态化,不管是params(get请求),还是data(post请求或者说带请求体的请求)。

word =  input("请输入您要搜索的内容:")
url = 'https://www.sogou.com/web'
params = {
    'query':word,
}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
}
html = requests.get(url=url,params=params,headers=headers).content.decode()
# 把请求来的页面源码写入到该文件
path = r'./{}.html'.format(word)
with open(path,'w',encoding='utf8') as f:
    f.write(html)

动态数据的爬取:

爬虫的第一步必须是判断目标网站是否是ajax动态生成的数据,用浏览器抓包工具,浏览器栏请求的肯定是第一个数据包,定位并找到它的Response看看,如果全是js代码肯定是ajax动态生成,如果不确定就在Response里面搜页面的某个数据,搜不到就证明是动态加载的,再去全局搜,就能定位到ajax在后台偷偷请求的数据包,我们再模拟这个ajax请求,就能把动态加载的数据(这个数据包)拿到。

爬肯德基的餐厅信息:

http://www.kfc.com.cn/kfccda/storelist/index.aspx

在这里插入图片描述
通过下图的全局搜索,锁定我们页面的资源来源于后台ajax的post请求,请求的数据包是下图这个,请求地址为下图的这个url:
在这里插入图片描述
模拟这个ajax的post请求:

headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.149 Safari/537.36',
}
url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
data = {
    "cname": "",
    "pid": "",
    "keyword": "北京",
    "pageIndex": 1,
    "pageSize": 10,
}
# data和params都是用来实现参数动态化的,如果是post请求,重心放在data。
json_str = requests.post(url=url,headers=headers,data=data).json()
for dict in json_str['Table1']:
	# 根据动态数据包的respnse的数据结构,这样才能拿到想要的位置信息
    position = dict['addressDetail']
    print(position)

而这只是第一页的数据,如果想要获取所有页码的数据,就要去分析ajax请求的请求体参数了。既然知道是动态获取,那就直接开启抓包,点第二页,直接锁定XHR,请求的url肯定是定死的(ajax请求局部刷新),只是请求体的pageIndex不一样,所以我直接动态化index。
在这里插入图片描述

url = 'http://www.kfc.com.cn/kfccda/ashx/GetStoreList.ashx?op=keyword'
for pageIndex in range(1,3):
    data = {
        "cname": "",
        "pid": "",
       	# 你甚至可以动态化keyword,全国每个省的每一页的门店信息
       	#"keyword": proc,
        "keyword": "北京",
        "pageIndex": pageIndex,
        "pageSize": 10,
    }
    # data和params都是用来实现参数动态化的,如果是post请求,重心放在data。
    json_str = requests.post(url=url,headers=headers,data=data).json()
    # print(json_str)
    for dict in str['Table1']:
        position = dict['addressDetail']
        print(position)

继续:爬取国家药监局每家企业的详情页的信息:

http://125.35.6.84:81/xk/

老规矩,进任意一个企业的详情页,查看该页面的数据书否是动态加载的数据。
在这里插入图片描述
找不到这条许可证数据,证明确实是前端ajax动态加载到页面上的,解决方法依然是全局搜索
在这里插入图片描述
在这里插入图片描述

得出结论:每一家企业的ajax请求地址是一样的,请求方式也是一样的,仅仅是data请求体那个唯一id不一样,结论:我们只需要拿到每个公司的这个加密id即可循环开爬

怎么找呢,肯定是去全局搜这个id,肯定能定位带一堆id串。
在这里插入图片描述
还真找到了。直接按照上图的参数和请求方式去拿到所有公司的id存到companyid_list列表中。
在这里插入图片描述
接着就动态化id,将这个id作为请求体,遍历id列表即可。

url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsById'
for id in companyid_list:
    data = {
        "id":id,
    }
    json_str = requests.post(url=url,headers=headers,data=data).json()
    businessPerson = json_str['businessPerson']
    epsAddress = json_str['epsAddress']
    print(businessPerson,epsAddress)

获取多页(前六页)企业id:

companyid_list = []
# 获取前6页的企业id
for page in range(1,7):
    url = 'http://125.35.6.84:81/xk/itownet/portalAction.do?method=getXkzsList'
    data = {
        "on":"true",
        "page":page,
        "pageSize":15,
        "conditionType":1,
    }
    json_str = requests.post(url=url,headers=headers,data=data).json()
    for dic in json_str["list"]:
        id = dic['ID']
        companyid_list.append(id)
print(companyid_list)

现在数据就会多很多,因为id列表增加成了前六页的企业id组成的列表:
在这里插入图片描述

爬图片方式:一是要二进制文件(content),二是要以二进制打开待存文件。

res = requests.get('https://dss3.bdstatic.com/70cFv8Sh_Q1YnxGkpoWK1HF6hhy/it/u=2534506313,1688529724&fm=26&gp=0.jpg',headers=headers).content
with open(r'./123.png','wb') as f:
    f.write(res)

梳理现在接触到的三种反爬机制:

robots协议,请求头UA检测,动态加载的数据。

如何判断爬取的页面数据是否是ajax请求动态生成的,基于抓包工具局部搜索(实际上一看response你就知道了,如果浏览器请求url对应返回的数据包全是或很多js代码只有很少的数据,肯定是动态生成的),是的话就在全局请求包中搜索页面上某个页面上的数据,定位到ajax请求回来的数据包,再模拟ajax请求拿动态数据。

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值