zoukankan      html  css  js  c++  java
  • 分析京东网站结构

    浏览器调试分析

    商品列表url分析

    打开京东网站,随便输入一个关键字,点开抓包工具(ctrl+F)

     看到不是动态加载的是不是有点激动?但是你拿到的并不是全数据,为什么这么说呢,往下看

    当滑动滚轮时,出现了新数据

     查看请求url及参数

     

    尝试去掉不必要的参数,经过多次的尝试发现,要获取到数据只需要想它发送请求就可以拿到数据:

    url:https://search.jd.com/s_new.php?keyword=电脑&page=1&s=30
    # 注意page与s的关系,注意最大页码的值(商品页面显示页码为100,那么你在拼接url时,最大页码必须是100*2)
    参数:   keyword:搜索的关键字   page:页码数   s:每一页的数据条数

    但是,你会发现他只能拿到三十几条左右的数据,而正常是当滚轮滑动到底端时会有六十几条数据,这时候不要慌,因为你会发现当url的page=2&s=60时,就会出现,原来滚轮滑动到底部后获取的新数据

    因此,当滚轮滑动到底部时,原来的1页,展示了两页的数据

    既然明白了他们的数据请求方式,那么拿到所有的商品列表就很简单了

     拿到后发送请求获取到response,进行xpath解析就可以了

    详情页评论分析  

    上面我们已经获取了商品列表页需要的数据,记得拿详情页的url

    接下来继续分析详情页数据接口的url:随便点击一个商品,抓包,全局搜索

     查看请求的url:

     分析url和参数:

    将这里的请求url输入浏览器地址栏,看能否拿到数据:

     很明显,可以拿到数据,接着我们看携带的参数

    url:https://club.jd.com/comment/productPageComments.action?callback=fetchJSON_comment98&productId=100006581268&score=0&sortType=5&page=0&pageSize=10&isShadowSku=0&fold=1
    
     参数:
            callback: fetchJSON_comment98  # 这是个回调函数
            productId: 100006581268           # 商品id
            score: 0                             # 不知道啥东西
            sortType: 5                        # 不知道啥东西
            page: 0                             # 评论的页码 
            pageSize: 10                      # 每页显示几条数据 
            isShadowSku: 0        
            fold: 1

    我们虽然拿到这些参数,但是,你会疑惑这些参数是不是通过js动态生成的?怎么获取这些参数呢?

    其实:对于这种情况来说,先不要老是想着找它的来源,因为有时候就单纯的获取数据来说,有些参数并不是必须要携带的

     这里,我们尝试去掉一些不必要的参数

    url:https://club.jd.com/comment/productPageComments.action?productId=100003383325&score=0&sortType=5&page=3&pageSize=10
    
    参数:
        productId:商品id
        score:不知道啥东西,但这个必须带
        sortType:同上
        page:评论的页码
        pageSize:每页评论的条数

    至此,我们的评论数据接口就搞定了

    解决只能爬取70条左右的评论的问题

    京东做了反扒机制,当你访问评率过快或者使用单个ip访问的时候只允许你拿70左右的数据,如何解决呢?

    ip代理池+设置请求发送的间隔时间:以scrapy框架为例:

    IP代理池(本人ip代理是从网上爬取的免费代理,存放在数据库中):

    下载器中间件文件:

    class AllJdDownloaderMiddleware:
        # Not all methods need to be defined. If a method is not defined,
        # scrapy acts as if the downloader middleware does not modify the
        # passed objects.
        conn = None
        cursor = None
        proxy_list = []
    
        def __init__(self):
            self.conn = pymysql.Connect(host=MYSQL_IPS_CONNECT['host'], user=MYSQL_IPS_CONNECT['user'],
                                        port=MYSQL_IPS_CONNECT['port'], password=MYSQL_IPS_CONNECT['password'],
                                        db=MYSQL_IPS_CONNECT['db_name'],
                                        charset='utf8')
            self.cursor = self.conn.cursor()
            sql = 'select ip,port,http_type from ips'
            try:
                self.cursor.execute(sql)
                # 取数据库中所有的ip
                all_ip = self.cursor.fetchall()
                if not all_ip:
                    raise ValueError('您没有代理ip了!')
                for ips in all_ip:
                    ip, port, http_type = ips
                    self.proxy_list.append(f"{http_type.lower()}s://{ip}:{port}")
            except Exception as e:
                print(e)
    
        @classmethod
        def from_crawler(cls, crawler):
            # This method is used by Scrapy to create your spiders.
            s = cls()
            crawler.signals.connect(s.spider_opened, signal=signals.spider_opened)
            return s
    
        def process_request(self, request, spider):
            request.meta['http_proxy'] = random.choice(self.proxy_list)
            request.cookie = COOKIE
    
            return None
    
        def process_response(self, request, response, spider):
            print(response['cookies'])
            if (spider.comment_url.split('?')[0] in request.url):
                if not response.text:
                    # 如果评论页面数量数据取不到,换代理重新请求
                    request.meta['http_proxy'] = random.choice(self.proxy_list)
                    return request
            return response
    
        def process_exception(self, request, exception, spider):
            # 捕获到异常请求,换代理ip,重新发送请求
            request.meta['http_proxy'] = random.choice(self.proxy_list)
            return request
    
        def spider_opened(self, spider):
            spider.logger.info('Spider opened: %s' % spider.name)

    设置请求发送间隔时间:

    settings.py

    DOWNLOAD_DELAY = 2 # 单位秒

    然后你就可以开搞了。

    本人此次项目获取的是每个商品的价格、好评、差评、好评度等数据 ,并未爬取评论,但数据接口是相同的,看一下运行结果

     总结一下分析的url:

    商品列表url:
    for page in range(1, 200):
        url = 'https://search.jd.com/s_new.php?keyword=%s&page=%d&s=%d' % ('电脑', page, page * 30)
    参数:
        keyword:搜索关键字
        page:列表页码
        s:展示的商品数量
        
    评论列表url:
    for page in range(0,100)
        url = 'https://club.jd.com/comment/productPageComments.action?productId=%s&score=0&sortType=5&page=%d&pageSize=%d' % ('100003383325',page,10)
    参数:
        productId=100003383325 # 商品id,其他参数不变
        score=0
        sortType=5
        page=0       # 评论页码数,
        pageSize=10  # 每页评论条数

    完。。。。。。。。。。。。。

  • 相关阅读:
    C++内存分配
    扩展哈夫曼编码
    用递归函数和栈操作逆序一个栈
    非递归遍历二叉树
    malloc/free和new/delete
    洗牌算法及其证明
    野指针问题
    计算编辑距离
    数组指针/指针数组的使用
    sizeof/strlen/length
  • 原文地址:https://www.cnblogs.com/kindvampire/p/12914102.html
Copyright © 2011-2022 走看看