本人长期出售超大量微博数据、旅游网站评论数据,并提供各种指定数据爬取服务,Message to YuboonaZhang@Yahoo.com。同时欢迎加入社交媒体数据交流群:99918768
前言
为了获取多源数据需要到各个网站获取一些景点的评论信息和图片,首先选到了携程和蚂蜂窝这两个网站,将一些爬取过程记录下来
携程
分析数据
首先我们去携程的鼓浪屿景点速览看一下我们要爬取的页面,大概发现有几十个景点,每个景点的结构应该都是差不多的,所以我们选择第一个景点进去看看具体的页面应该怎么爬取。
[站外图片上传中...(image-14bb2e-1513948356467)]
我们需要的是红圈的部分,很容易可以知道这个评论页面是动态加载的,所以不能直接用bs4或者正则直接提取元素,我们需要分析一下页面动态传输的接口。打开chrome审查元素,切换到network查看一下传输的内容,首先清空内容避免干扰,然后点击下一页,我们可以得到
[站外图片上传中...(image-f5a92b-1513948356467)]
通过查看传回的数据我们可以得到这就是我们所要的接口,使用的是post进行传输,传输的Form Data 有很多字段,大致可以猜测出来
poiID 是景点的poiID </br> pagenow 是当前的页数 </br> star 是评分1-5,0代表全部 </br> resourceId 是一个每个资源对应的值
爬取的时候只需要改变这些值就可以根据自己的需求爬取内容了,但是需要注意的事携程的pagenow最多只能获取100页,而且poiID和resourceId的值是没有规律的,需要我们逐个景点查看...我自己依次找了鼓浪屿所有景点的值,并存在文本中,文末有github的共享。
建库
我们要做的第一件事就是想好数据库的结构,我选择的还是使用mysql,具体的结构如下:
[站外图片上传中...(image-b486a2-1513948356467)]
获取数据
这个我就不具体分析了,也不难,就是有几个坑要注意一下。
第一,不是所有评论都有景色,性价比之类的评分,所以这里要加一个判断。</br> 第二,原来是有出行时间这一项的,现在好像没有了额。</br> 第三,评论文本可能会出现单引号,插入数据库会出现错误,要转义或者替代一下。</br> 第四,抓取速度不要太快,携程反扒还是比较厉害的。
蚂蜂窝
分析数据
同样,蚂蜂窝的数据也是动态加载的,用相同的方法查看分析数据接口。
[站外图片上传中...(image-83988-1513948356467)]
可以看到蚂蜂窝的数据获取方式是get,我们可以找出请求的url的规律。经过比较不同景点和不同页面的数据,我们发现参数的改变主要在两个地方,一个是poiid我用href代替,一个是页数我用num代替。获取景点的评论数据只要改变这两个值就可以了
url='http://pagelet.mafengwo.cn/poi/pagelet/poiCommentListApi?callback=jQuery18105332634542482972_1511924148475¶ms=%7B%22poi_id%22%3A%22{href}%22%2C%22page%22%3A{num}%2C%22just_comment%22%3A1%7D'
获取每个景点的poi
这个不是post请求我们就不必一个个景点去获取参数了,我们可以访问这个站点来发现所有的用户,然而这个站点的数据也是动态加载的
[站外图片上传中...(image-45564c-1513948356467)]
根据上面的图片我们可以清晰的看到我们只需要传入页码数就可以得到所有的景点的poiid,然后根据这些poiid我们就可以得到所有的评论数据,这一部分我们用一个函数来处理
def get_param():
# 获取所有景点的参数
total = []
router_url = 'http://www.mafengwo.cn/ajax/router.php'
for num in range(1, 6):
params = {
'sAct': 'KMdd_StructWebAjax|GetPoisByTag',
'iMddid': 12522,
'iTagId': 0,
'iPage': num
}
pos = requests.post(url=router_url, data=params, headers=headers).json()
soup_pos = BeautifulSoup(pos['data']['list'], 'lxml')
result = [{'scenery': p['title'], 'href': re.findall(re.compile(r'/poi/(\d+).html'), p['href'])[0]} for p in
soup_pos.find_all('a')]
total.extend(result)
return total
其余部分相似,不再过多说明。
1:http://you.ctrip.com/sight/gulangyu120058.html
2:http://you.ctrip.com/sight/gulangyu120058/57405.html
3:http://www.mafengwo.cn/jd/12522/gonglve.htmlonaZhang@Yahoo.com
前言
为了获取多源数据需要到各个网站获取一些景点的评论信息和图片,首先选到了携程和蚂蜂窝这两个网站,将一些爬取过程记录下来
携程
分析数据
首先我们去携程的鼓浪屿景点速览看一下我们要爬取的页面,大概发现有几十个景点,每个景点的结构应该都是差不多的,所以我们选择第一个景点进去看看具体的页面应该怎么爬取。
我们需要的是红圈的部分,很容易可以知道这个评论页面是动态加载的,所以不能直接用bs4或者正则直接提取元素,我们需要分析一下页面动态传输的接口。打开chrome审查元素,切换到network查看一下传输的内容,首先清空内容避免干扰,然后点击下一页,我们可以得到
通过查看传回的数据我们可以得到这就是我们所要的接口,使用的是post进行传输,传输的Form Data 有很多字段,大致可以猜测出来
poiID 是景点的poiID </br> pagenow 是当前的页数 </br> star 是评分1-5,0代表全部 </br> resourceId 是一个每个资源对应的值
爬取的时候只需要改变这些值就可以根据自己的需求爬取内容了,但是需要注意的事携程的pagenow最多只能获取100页,而且poiID和resourceId的值是没有规律的,需要我们逐个景点查看...我自己依次找了鼓浪屿所有景点的值,并存在文本中,文末有github的共享。
建库
我们要做的第一件事就是想好数据库的结构,我选择的还是使用mysql,具体的结构如下:
获取数据
这个我就不具体分析了,也不难,就是有几个坑要注意一下。
第一,不是所有评论都有景色,性价比之类的评分,所以这里要加一个判断。</br> 第二,原来是有出行时间这一项的,现在好像没有了额。</br> 第三,评论文本可能会出现单引号,插入数据库会出现错误,要转义或者替代一下。</br> 第四,抓取速度不要太快,携程反扒还是比较厉害的。
蚂蜂窝
分析数据
同样,蚂蜂窝的数据也是动态加载的,用相同的方法查看分析数据接口。
可以看到蚂蜂窝的数据获取方式是get,我们可以找出请求的url的规律。经过比较不同景点和不同页面的数据,我们发现参数的改变主要在两个地方,一个是poiid我用href代替,一个是页数我用num代替。获取景点的评论数据只要改变这两个值就可以了
url='http://pagelet.mafengwo.cn/poi/pagelet/poiCommentListApi?callback=jQuery18105332634542482972_1511924148475¶ms=%7B%22poi_id%22%3A%22{href}%22%2C%22page%22%3A{num}%2C%22just_comment%22%3A1%7D'
获取每个景点的poi
这个不是post请求我们就不必一个个景点去获取参数了,我们可以访问这个站点来发现所有的用户,然而这个站点的数据也是动态加载的
根据上面的图片我们可以清晰的看到我们只需要传入页码数就可以得到所有的景点的poiid,然后根据这些poiid我们就可以得到所有的评论数据,这一部分我们用一个函数来处理
def get_param():
# 获取所有景点的参数
total = []
router_url = 'http://www.mafengwo.cn/ajax/router.php'
for num in range(1, 6):
params = {
'sAct': 'KMdd_StructWebAjax|GetPoisByTag',
'iMddid': 12522,
'iTagId': 0,
'iPage': num
}
pos = requests.post(url=router_url, data=params, headers=headers).json()
soup_pos = BeautifulSoup(pos['data']['list'], 'lxml')
result = [{'scenery': p['title'], 'href': re.findall(re.compile(r'/poi/(\d+).html'), p['href'])[0]} for p in
soup_pos.find_all('a')]
total.extend(result)
return total
其余部分相似,不再过多说明。