zoukankan      html  css  js  c++  java
  • 吴裕雄--天生自然PYTHON爬虫:爬取某一大型电商网站的商品数据

    首先观察、分析网站

    网址:https://touch.qunar.com

     接下按F12进入浏览器开发者模式,并且点击  自由行  选项进入到自由行频道,如下图:

     

     

    Request URL:
    https://dujia.qunar.com/golfz/destination/tejiaLeft?num=6&tms=pc_jrth&dep=%E6%B7%B1%E5%9C%B3&callback=jQuery17203372573055312833_1579011479291&_=1579011479776
    单击任意一个城市,通过观察可以发现数据在XHR(用XMLHttpRequest方法来获取JavaScript)
    其中RequestURL是以%开头的字符串是中文编译成的字符串,由于服务器不能识别中文字符,所以这里可以使用第三方工具解码查看。
    这里使用的是零一工具。下载网址:http://www.muyaotech.com/about_muyao.php?cid=40
    安装过程如下:

     

     

     

     

     任意点击一张图片,再从开发者模式的header那里查看

    Request URL:
    https://dujia.qunar.com/golfz/routeList?isTouch=0&t=all&extendFunction=%E8%87%AA%E7%94%B1%E8%A1%8C&q=%E5%8E%A6%E9%97%A8&d=%E6%B7%B1%E5%9C%B3&s=all&qs_ts=1579012214105&tf=pcindex_free&tm=djnull&sourcepage=list&userResident=%E6%B7%B1%E5%9C%B3&random=748656&aroundWeight=1&qssrc=eyJ0cyI6IjE1NzkwMTIyMTQxMDUiLCJzcmMiOiJhbGwuZW52YiIsImFjdCI6InNlYXJjaCIsInJhbmRvbSI6Ijc0ODY1NiJ9&m=p%2Cpr%2Ciso%2CisSd%2Chco%2Chtl%2Cactivities%2Cns%2Cnep%2Cgg%2CrefundAnytime%2CtruthfulDesc&displayStatus=pc&ddf=true

     可以看到上面的URL是UTF8编码的,解码后就可以看到中文部分了。

    Request URL:
    https://touch.dujia.qunar.com/list?modules=list%2CbookingInfo%2CactivityDetail&dep=%E5%8C%97%E4%BA%AC&query=%E5%8E%A6%E9%97%A8%E8%87%AA%E7%94%B1%E8%A1%8C&dappDealTrace=true&mobFunction=%E6%89%A9%E5%B1%95%E8%87%AA%E7%94%B1%E8%A1%8C&cfrom=zyx&it=dujia_hy_destination&date=&needNoResult=true&originalquery=%E5%8E%A6%E9%97%A8%E8%87%AA%E7%94%B1%E8%A1%8C&limit=0,24&includeAD=true&qsact=search

    由于这里的目标是获取整个自由行的产品列表,因此还需要获取出发站点的列表,从不同的城市出发,会有不用的产品。

    返回自由行的首页,单击搜索框左侧的出发站点,如下图:

     切换到Headers界面:

     可以看到此时目标的URL是:https://touch.dujia.qunar.com/depCities.qunar

    开始分析该网站的爬虫工作流程分析步骤:

    1 获取出发地站点列表

    2 获取旅游景点列表

    3 获取景点产品列表

    4 存储数据

    #首先获取出发站点,代码如下:
    import requests
    
    url = 'https://touch.dujia.qunar.com/depCities.qunar'
    strhtml = requests.get(url)
    dep_dict = strhtml.json()
    for dep_item in dep_dict['data']:
        for dep in dep_dict['data'][dep_item]:
            print(dep)

     。。。。。。。。。

     

     在获取数据的时候需要将最后一个callback参数删掉。因此目标URL如下:

    https://touch.dujia.qunar.com/golfz/sight/arriveRecommend?dep=%E6%B7%B1%E5%9C%B3&exclude=&extensionImg=255,175

    #然后根据出发地站点获取目的地,代码如下:
    import time
    import urllib
    import requests
    
    url = 'https://touch.dujia.qunar.com/depCities.qunar'
    strhtml = requests.get(url)
    dep_dict = strhtml.json()
    for dep_item in dep_dict['data']:
        for dep in dep_dict['data'][dep_item]:
            print(dep)
            url = 'https://touch.dujia.qunar.com/golfz/sight/arriveRecommend?dep={}&exclude=&extensionImg=255,175'.format(urllib.request.quote(dep))
            time.sleep(3)
            strhtml = requests.get(url)
            arrive_dict = strhtml.json()
            for arr_item in arrive_dict['data']:
                for arr_item_1 in arr_item['subModules']:
                    for query in arr_item_1['items']:
                        print(query['query'])
            

     .................

    到达的 目的地有很多,上面这段代码也要运行很长时间,运行截图也是一部分的,篇幅有限还有很多地点没有展示,但很容易看到许多的目的地是重复的,

    原因也很简单一个目的地多数都是对应这多个出发点的,按出发点分别来找目的地的话最后打印寻找到的目的地肯定有许多也就是重复的了,所以接下来

    就是要对目的地进行去重,代码修改后,如下:

    #然后根据出发地站点获取目的地,代码如下:
    import time
    import urllib
    import requests
    
    url = 'https://touch.dujia.qunar.com/depCities.qunar'
    strhtml = requests.get(url)
    dep_dict = strhtml.json()
    for dep_item in dep_dict['data']:
        for dep in dep_dict['data'][dep_item]:
            #这里声明一个列表a用来保存当前这个出发点对应的所有目的地
            a = []
            print(dep)
            url = 'https://touch.dujia.qunar.com/golfz/sight/arriveRecommend?dep={}&exclude=&extensionImg=255,175'.format(urllib.request.quote(dep))
            time.sleep(3)
            strhtml = requests.get(url)
            arrive_dict = strhtml.json()
            for arr_item in arrive_dict['data']:
                for arr_item_1 in arr_item['subModules']:
                    for query in arr_item_1['items']:
                        #如果当前这个目的地不在a中的话,那就添加进去,否则不添加,这样就可以达到目的地去重的目的了
                        if(query['query'] not in a):
                            a.append(query['query'])
            #打印当前出发点所有对应的不重复的目的地点
            print(a)
            

     这样每个出发点对应的目的点打印出来也好看清晰了许多。

    完成了出发点和目的地的构建之后,接下来就要获取产品列表了。代码如下:

     

    #获取产品列表
    import time
    import urllib
    import pymongo
    import requests
    
    #使用MongoDB创建数据库、表
    client = pymongo.MongoClient('localhost',27017)
    book_qunar = client['qunar']
    sheet_qunar_zyx = book_qunar['qunar_zyx']
    
    #获取产品
    url = 'https://touch.dujia.qunar.com/depCities.qunar'
    strhtml = requests.get(url)
    dep_dict = strhtml.json()
    for dep_item in dep_dict['data']:
        for dep in dep_dict['data'][dep_item]:
            #这里声明一个列表a用来保存当前这个出发点对应的所有目的地
            a = []
            url = 'https://touch.dujia.qunar.com/golfz/sight/arriveRecommend?dep={}&exclude=&extensionImg=255,175'.format(urllib.request.quote(dep))
            time.sleep(3)
            strhtml = requests.get(url)
            arrive_dict = strhtml.json()
            for arr_item in arrive_dict['data']:
                for arr_item_1 in arr_item['subModules']:
                    for query in arr_item_1['items']:
                        #如果当前这个目的地不在a中的话,那就添加进去,否则不添加,这样就可以达到目的地去重的目的了
                        if(query['query'] not in a):
                            a.append(query['query'])
            #逐个地取出当前出发点对应的目的地item
            for item in a:
                url = 'https://touch.dujia.qunar.com/list?modules=list%2CbookingInfo%2CactivityDetail&dep={}&query={}&dappDealTrace=true&mobFunction=%E6%89%A9%E5%B1%95%E8%87%AA%E7%94%B1%E8%A1%8C&cfrom=zyx&it=dujia_hy_destination&date=&needNoResult=true&originalquery={}&limit=0,24&includeAD=true&qsact=search'.format(urllib.request.quote(dep),urllib.request.quote(item),urllib.request.quote(item))
                time.sleep(3)
                strhtml = requests.get(url)
                #获取当前目的地的产品数量
                routeCount = int(strhtml.json()['data']['limit']['routeCount'])
                for limit in range(0,routeCount,24):
                    url = 'https://touch.dujia.qunar.com/list?modules=list%2CbookingInfo%2CactivityDetail&dep={}&query={}&dappDealTrace=true&mobFunction=%E6%89%A9%E5%B1%95%E8%87%AA%E7%94%B1%E8%A1%8C&cfrom=zyx&it=dujia_hy_destination&date=&needNoResult=true&originalquery={}&limit={},24&includeAD=true&qsact=search'.format(urllib.request.quote(dep),urllib.request.quote(item),urllib.request.quote(item),limit)
                    time.sleep(3)
                    strhtml = requests.get(url)
                    #用一个字典保存当前这个产品的信息
                    result = {
                        'date':time.strftime('%Y-%m-%d',time.localtime(time.time())),
                        'dep':dep,
                        'arrive':item,
                        'limit':limit,
                        'result':strhtml.json()
                    }
                    #向数据库中插入这条产品信息记录
                    sheet_qunar_zyx.insert_one(result)
                    print('成功!')

    爬取的数据量是非常大的 代码需要运行非常长的时间,运行代码打开pycharm就可以观察到保存的数据了(前提是pycharm已经安装好了mongo的插件了以及本地安装配置好mongodb了)

     

     
     
     
  • 相关阅读:
    APB协议
    AHB总线协议(一)
    C++内存机制中内存溢出、内存泄露、内存越界和栈溢出的区别和联系
    深入理解C++内存管理机制
    c/c++内存机制(一)(转)
    与临时对象的斗争(下)
    与临时对象的斗争(上)ZZ
    C++异常处理解析: 异常的引发(throw), 捕获(try catch)、异常安全
    qt5信息提示框QMessageBox用法
    红黑树
  • 原文地址:https://www.cnblogs.com/tszr/p/12193744.html
Copyright © 2011-2022 走看看