ps:课前规矩,ps一下。上节我们讲了最简单的爬虫,但是在真实的网络环境下,并不是所有的网页都能用那样的方式抓取,用ajax异步请求数据的网页就没办法用如上方式,那么我们今天就来看看如何抓取异步加载数据的网页。(找网页的时候发现简书的部分页面也是用这种方式加载的,忍了很久还是放过了简书~~)
代码预览
#coding:utf-8
from bs4 import BeautifulSoup
import requests
import json
import pymongo
url = 'http://www.guokr.com/scientific/'
def dealData(url):
client = pymongo.MongoClient('localhost', 27017)
guoke = client['guoke']
guokeData = guoke['guokeData']
web_data = requests.get(url)
datas = json.loads(web_data.text)
print datas.keys()
for data in datas['result']:
guokeData.insert_one(data)
def start():
urls = ['http://www.guokr.com/apis/minisite/article.json?retrieve_type=by_subject&limit=20&offset={}&_=1462252453410'.format(str(i)) for i in range(20, 100, 20)]
for url in urls:
dealData(url)
start()
代码剖析
细心的同学可能发现了,这和昨天的没什么区别啊0.0。其实不是这样的,这次我们要抓取的数据是果壳网的科学人分页,如果直接通过requests.get('http://www.guokr.com/scientific/')
你会发现我们要的数据都不在返回网页源代码中,这是因为我们要的数据都是通过ajax的方式异步加载的。那我们应该如何抓取这部分内容呢?首先用浏览器打开我们要抓的网页
随便选择一个地方点开查看元素,细心的同学发现我们这次不用chrome改用火狐了,原因一会告诉大家~
2.png选择网络标签和XHR分页,然后我们向下滑动鼠标滚轮可以发现一个一个的GET请求被列了出来,这便是ajax异步加载的数据,此时进行观察,如下图:
3.png我们可以看到每次请求的url,然后通过观察url变化我们找到了规律,每次的偏移量offset都不一样,代表了我们取出从什么位置取出多少条数据,观察完url规律,我们点击其中一条url,切换到响应分页,如下图所示:
4.png
我们可以看到请求回来的数据格式是json,而且数据结构非常清晰,这也是我选用火狐的原因,我们一眼可以找出我们需要的数据就在result这个key下面。
下面进入我们的代码,start()中拼接url的代码我就不在赘述,我们可以看到这次和上次不同的是引入了两个新库
import json
import pymongo
json库是python自带的json解析库,功能够我们使用的。pymongo是python和mongoDB交互用的库。首先我们来看这段代码:
client = pymongo.MongoClient('localhost', 27017)
guoke = client['guoke']
guokeData = guoke['guokeData']
PS:一定记得在执行这段代码之前先打开你本地的mongoDB数据库,我在环境配置章节有讲怎么安装mongoDB,不会的同学请参见第二章环境配置。
第一句,建立一个pymongo的数据交互客户端,第二句选择名为guoke的database,注意:如果有名为guoke的database则会直接使用已有的,如果没有则会自动建立。第三句选择guoke数据库中名为guokeData的collection。
接下来:
datas = json.loads(web_data.text)
print datas.keys()
用json库加载我们取出的数据,然后打印出数据的keys,
5.png
我们可以看到和我们在火狐浏览器中的数据结构一致,我们需要用的是其中的result字段,刚刚我们通过火狐观察到result是一个list,然后我们遍历result依次存入guokeData这个collection之中。所以,最后一句
guokeData.insert_one(data)
就是给collection中插入一条数据,我个人很喜欢抓取返回格式是json的网站,因为数据格式很规范,可以直接存入mongo中任意取用,操作简单。不用做数据序列化操作,而我们上节那样解析出来的数据要存入数据库就需要做序列化操作。
下来时代码执行完毕后数据库的情况,可以看到我们的数据已经尽数插入数据库
![6.png]ACURNVC.png](https://img.haomeiwen.com/i1957582/b3cd1e541ed57afd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
可以看到很舒服的数据结构。
至此,这一节的内容告一段落,当然,并不是所有的异步加载网页都需要我们去通过观察法获取url然后再采集,这样岂不是会很累,下节将向大家介绍一种非常舒服的方式去做这件事。
写在最后
惯例,最佳实践的前两步我帮你们做完了,有兴趣的同学可以看一下扩展作业哦。
作业:抓取http://rent.591.com.hk/ 这个网站租房的信息,信息都是采用ajax异步加载的方式。而且刚好和我们上节的内容是个强烈对比,不能通过更改url获取分页的数据了,很适合练手~~
有兴趣的同学可以加群498945822一起交流学习哦~~
发现问题的同学欢迎指正,直接说就行,不用留面子,博主脸皮厚!
网友评论
client = pymongo.MongoClient('localhost', 27017)
guoke = client['guoke']
guokeData = guoke['guokeData']
在dealData这段diamante里面我觉得上面这三个完全可以放到外面,不然每次解析完一个url,我就要重新开启一次数据库连接。第一次用mongo,指教一下。