携程网国外酒店数据采集

采集流程分析

经分析,采集流程可以简化为如下:

1. 国外城市列表

https://m.ctrip.com/webapp/hotel/j/hoteldetail/dianping/api/static/city?oversea=true&index=H

JSON格式返回,如下示例,可以通过index参数遍历A-Z获取所有国外城市。

2. 根据城市信息构造出城市下酒店列表的首页链接:http://hotels.ctrip.com/international/washington26363

http://hotels.ctrip.com/international/ + seo(去掉括号及内部内容) + cityID

下载所有列表分页。从酒店列表页获取酒店详情页链接和酒店最低价。

3. 进入酒店详情页提取字段:

例如http://hotels.ctrip.com/international/2081845.html(去掉多余参数)

详情页面源码内有如下有用信息(下简称JSON信息),下面提取字段的时候有些可以直接用上。

采集程序编写

上面分析了基本的采集流程,下来着手编写程序,如果遇到问题就边写边调试吧。

程序开头定义好数据库相关信息:

# 连接数据库

client = pymongo.MongoClient()

# 指定数据库

db = client['数据库名']

# 指定集合

collection = db['集合名']

# 给url和酒店id字段创建索引

collection.ensure_index([('hotel_id', pymongo.ASCENDING)])

collection.ensure_index([('url', pymongo.ASCENDING)])

在程序编写、调试运行过程中,就发现网站的反采集策略做的十分严格,多线程也不能很奏效的快速采集到数据,那在这就采用多进程结合多线程方法进行采集了。

要注意的是进程的数量要合理,过多就会大量消耗系统内存导致系统卡死。下面就直接给出写好的多进程代码块,主要注释都写在程序里了:

def start_multiple_procs():

"""启动多进程

"""

# 创建多进程

procs = []

# 启动采集进程

cmd_args = ['python', 'ctrip_aa.py']

# 遍历所有国外城市列表 - 把每4个字母对应的链接加入到一个进程里,然后把进程加入进程列表里

inti_tasks = []

for cha in string.ascii_uppercase:

link = 'https://m.ctrip.com/webapp/hotel/j/hoteldetail/dianping/api/static/city?oversea=true&index={}'.format(cha)

inti_tasks.append(link)

procs_num = int(math.ceil(float(len(inti_tasks))/4))

# 得到进程总数,遍历进程数, 每个进程中加入任务列表

for num in range(0, procs_num):

proc_num = inti_tasks[num*4:num*4+4]

procs.append(subprocess.Popen(cmd_args + proc_num))

# 生成结束所有客户端进程脚本

with open('kill-clients.sh', 'w') as f:

f.write('kill -9 %s' % ' '.join([str(proc.pid) for proc in procs]))

os.system('chmod +x kill-clients.sh')

# 等待各子进程结束

common.logger.info('Waitting for all subprocesses(%s) to finish.' % len(procs))

for proc in procs:

proc.wait()

common.logger.info('All subprocesses have stopped.')

调试过程中发现pc端的酒店列表分页有显示数量限制,而移动端的没有。但是移动端页面列表加载是通过Ajax方法请求得到的。使用Fiddler辅助分析下,我们能找到正确的请求url,headers, data。

通过上述代码能尽可能全面的采集到国外酒店详情页链接。下来就要在详情页提取字段信息了,提取字段方法单独写一个模块,方便调试。

在详情页存在的难点也就是几处需要通过Ajax方法加载的数据,好在我们都可以通过Fiddler一点点拨开迷雾,得到想要的数据。

写在最后

本项目采集程序写完了,要多进程运行程序的话,我们要正确添加参数,程序文件是ctrip_aa.py,启动如下:

if__name__=='__main__':

if'--test'insys.argv:

test()

elif'--start_multiple_procs'insys.argv:

start_multiple_procs()

启动:python ctrip_aa.py --start_multiple_procs

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20181006G02SVH00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码关注腾讯云开发者

领取腾讯云代金券