文档章节

手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取

游牧民族
 游牧民族
发布于 2016/05/12 17:35
字数 2251
阅读 183
收藏 11
点赞 2
评论 0

系列教程:

手把手教你写电商爬虫-第一课 找个软柿子捏捏

手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫

 

看完两篇,相信大家已经从开始的小菜鸟晋升为中级菜鸟了,好了,那我们就继续我们的爬虫课程。

上一课呢一定是因为对手太强,导致我们并没有完整的完成尚妆网的爬虫。

吭吭~,我们这一课继续,争取彻底搞定尚妆网,不留任何遗憾。

我们先回顾一下,上一课主要遗留了两个问题,两个问题都和ajax有关。

1、由于是ajax加载下一页,导致下一页url并不会被系统自动发现。

2、商品页面的价格是通过ajax加载的,我们直接从网页中获取不到信息本身。

好了,我们先解决第一个问题:

第一个问题实际上是一个爬虫中比较常见的问题,即url的发现,默认情况下,URL的发现是神箭手框架自动处理的,但是如果在ajax的情况下,框 架则无从发现url,这个时候就需要我们自己手动处理url的发现,这里,神箭手给我们提供了一个很方便的回调函数让我们来自己处理url的发现:

onProcessHelperUrl(url, content, site)

这个回调函数有两个参数,分别是当前处理的页面对象和整个爬取站的对象,我们可以通过获取页面对象的内容来分析是否有我们需要的新一页的url,通过 site.addUrl()方法加入到url队列中既可。这里我们可以看到,当超出页数的时候,尚妆网会给我们返回一个这样的页面,我们就知道页数超过 了,不需要在加入新的页url:

 

 

这个页面我们很好判断,只需要看内容中是否有"无匹配商品"关键字既可。

这里我们需要一些基础的js能力,代码如下:

    configs.onProcessHelperUrl = function(url, content, site){  
        if(!content.indexOf("无匹配商品")){  
            //如果没有到最后一页,则将页数加1  
            var currentPage = parseInt(url.substring(url.indexOf("&page=") + 6));  
            var page = currentPage + 1;  
            var nextUrl = url.replace("&page=" + currentPage, "&page=" + page);  
            site.addUrl(nextUrl);  
        }  
    }  

 

原理很简单,如果内容中没有无匹配商品这个关键词的时候,则把当前页面的下一页加入的待爬队列中。
好了,ajax分页问题彻底解决,下面来看这个最棘手的ajax内容加载的问题,也就是如何获取到商品页面中的价格信息

 

首先,遇到这类问题,我们通常有两个思路:

1、通过js引擎将整个页面渲染出来之后,在去做内容抽取,这个方案对于一些复杂js页面是唯一解决方案,用神箭手框架来处理也很简单,不过由于需要执行js,导致抓取速度很慢,不到不得已情况,我们先不使用这个核武器

2、通过刚刚处理分页的经验,我们可以预先分析ajax请求,然后将这一步多出来的请求和原来的页面请求做一个关联。这种方案适合比较简单的js页面中。

 

OK,介绍完思路,根据经验,我们感觉尚妆网的ajax加载并没有十分复杂,所以我们选择方案二来处理这种ajax页面加载。

同样的,首页我们通过chrome开发者工具,抓取到这个ajax请求,这里教大家一个小窍门,开发者工具中,可以筛选请求对象未xhr,这种就是异步请求,我们就很容易发现我们的嫌疑url:

http://item.showjoy.com/product/getPrice?skuId=22912

我们在页面中找一下这个22912怎么提取最方便,我们很快就发现了一个标签:

    <input type="hidden" value="22912" id="J_UItemId" />  

 

这个标签很干净,获取的xpath也很简单:

//input[@id="J_UItemId"]/@value

 

这样就好办了,我们再看下这个页面请求的结果是什么:

{"count":0,"data":{"discount":"6.2","discountMoney":"43.00","originalPrice":112,"price":"69.00","showjoyPrice":"69.00"},"isRedirect":0,"isSuccess":0,"login":0}

 

可以看出来,是一个典型的json对象,这个就好办了,神箭手框架中给我们提供了通过jsonpath提取内容的方式,可以很简单的提取到价格对象,即price对应的值。

 

那最后我们怎么才能关联这个请求呢?这里也是框架中提供的一个方案,叫做attachedUrl,专门用来解决关联请求的请求的问题,也就是某一个字段的值可以通过一个关联请求的内容中抽取出来。语法我就不介绍了,直接上代码吧:

    {  
      name: "skuid",  
      selector: "//input[@id='J_UItemId']/@value",  
    },  
    {  
      name: "price",  
      sourceType: SourceType.AttachedUrl,  
      attachedUrl: "http://item.showjoy.com/product/getPrice?skuId={skuid}",  
      selectorType: SelectorType.JsonPath,  
      selector: "$.data.price",  
    }  

 

简 单介绍一下attachedUrl的用法,首先我们要设置sourceType为attachedUrl,同时我们要设置一个attachedUrl,即 为关联请求的地址,其中由于有一个值是动态的,所以我们需要在这个抽取项之前先抽取一下这个动态的值,所以我们增加了一个抽取项的名字叫做skuid,在 attachedUrl中的调用方法为{skuid},真实请求时,该项就会被自动替换成我们上一个skuid抽取项抽取到的值。接着,由于我们获取到的 是json返回,因此我们抽取的方式应该是通过jsonpath,最后,写一个抽取规则既可,jsonpath比xpath更加简单,相信大家一看就懂 了。

 

好了,弄了这么多,完整的代码如下:

    var configs = {  
        domains: ["www.showjoy.com","list.showjoy.com","item.showjoy.com"],  
        scanUrls: ["http://list.showjoy.com/search/?q=cateIds%3A1,cateName%3A%E9%9D%A2%E8%86%9C"],  
        contentUrlRegexes: ["http://item\\.showjoy\\.com/sku/\\d+\\.html"],  
        helperUrlRegexes: ["http://list\\.showjoy\\.com/search/\\?q=cateIds%3A1,cateName%3A%E9%9D%A2%E8%86%9C(\\&page=\\d+)?"],//可留空  
        fields: [  
            {  
                // 第一个抽取项  
                name: "title",  
                selector: "//h3[contains(@class,'choose-hd')]",//默认使用XPath  
                required: true //是否不能为空  
            },  
            {  
                // 第二个抽取项  
                name: "comment",  
                selector: "//div[contains(@class,'dtabs-hd')]/ul/li[2]",//使用正则的抽取规则  
                required: false //是否不能为空  
            },  
            {  
                // 第三个抽取项  
                name: "sales",  
                selector: "//div[contains(@class,'dtabs-hd')]/ul/li[3]",//使用正则的抽取规则  
                required: false //是否不能为空  
            },  
            {  
                name: "skuid",  
                selector: "//input[@id='J_UItemId']/@value",  
            },  
            {  
                name: "price",  
                sourceType: SourceType.AttachedUrl,  
                attachedUrl: "http://item.showjoy.com/product/getPrice?skuId={skuid}",  
                selectorType: SelectorType.JsonPath,  
                selector: "$.data.price",  
                  
            }  
        ]  
    };  
      
    configs.onProcessHelperUrl = function(url, content, site){  
        if(!content.indexOf("无匹配商品")){  
            //如果没有到最后一页,则将页数加1  
            var currentPage = parseInt(url.substring(url.indexOf("&page=") + 6));  
            var page = currentPage + 1;  
            var nextUrl = url.replace("&page=" + currentPage, "&page=" + page);  
            site.addUrl(nextUrl);  
        }  
        return true;  
    }  
    var crawler = new Crawler(configs);  
    crawler.start();  

 

 

终于搞定了,我们赶紧测试一下爬取的结果吧:

 

欣赏自己艰苦的劳动成果是不是很有成就感,不过现在的爬取结果依然有些美中不足,评论数和销售额拿到的都是一个完整的句子,而我们希望得到的是具体的数字,这个怎么操作呢?这个其实就是一个字段抽取到之后的进一步处理,框架中给我们提供了一个回调函数为:

afterExtractField(fieldName, data)

函数会将抽取名和抽取到的数据传进来,我们只需要通过js的字符串处理函数对数据进行进一步加工既可,直接上完整的修改过的代码:

var configs = {  
    domains: ["www.showjoy.com","list.showjoy.com","item.showjoy.com"],  
    scanUrls: ["http://list.showjoy.com/search/?q=cateIds%3A1,cateName%3A%E9%9D%A2%E8%86%9C"],  
    contentUrlRegexes: ["http://item\\.showjoy\\.com/sku/\\d+\\.html"],  
    helperUrlRegexes: ["http://list\\.showjoy\\.com/search/\\?q=cateIds%3A1,cateName%3A%E9%9D%A2%E8%86%9C(\\&page=\\d+)?"],//可留空  
    fields: [  
        {  
            // 第一个抽取项  
            name: "title",  
            selector: "//h3[contains(@class,'choose-hd')]",//默认使用XPath  
            required: true //是否不能为空  
        },  
        {  
            // 第二个抽取项  
            name: "comment",  
            selector: "//div[contains(@class,'dtabs-hd')]/ul/li[2]",//使用正则的抽取规则  
            required: false //是否不能为空  
        },  
        {  
            // 第三个抽取项  
            name: "sales",  
            selector: "//div[contains(@class,'dtabs-hd')]/ul/li[3]",//使用正则的抽取规则  
            required: false //是否不能为空  
        },  
        {  
            name: "skuid",  
            selector: "//input[@id='J_UItemId']/@value",  
        },  
        {  
            name: "price",  
            sourceType: SourceType.AttachedUrl,  
            attachedUrl: "http://item.showjoy.com/product/getPrice?skuId={skuid}",  
            selectorType: SelectorType.JsonPath,  
            selector: "$.data.price",  
              
        }  
    ]  
};  
  
configs.onProcessHelperUrl = function(url, content, site){  
    if(!content.indexOf("无匹配商品")){  
        //如果没有到最后一页,则将页数加1  
        var currentPage = parseInt(url.substring(url.indexOf("&page=") + 6));  
        var page = currentPage + 1;  
        var nextUrl = url.replace("&page=" + currentPage, "&page=" + page);  
        site.addUrl(nextUrl);  
    }  
    return true;  
}  
configs.afterExtractField = function(fieldName, data){  
    if(fieldName == "comment" || fieldName == "sales"){  
        var regex = /.*((\d+)).*/;  
        return (data.match(regex))[1];  
    }  
    return data;  
}  
var crawler = new Crawler(configs);  
crawler.start(); 

 


我们判断了如果是comment和sales抽取项时,通过正则直接匹配到括号里的数字,这里注意,网页上的括号本来是全角的括号,所以千万不要写错了。

 

这次终于可以开心的看着自己的爬虫数据结果了:

 

对爬虫感兴趣的童鞋可以加qq群讨论:342953471。

© 著作权归作者所有

共有 人打赏支持
游牧民族
粉丝 7
博文 9
码字总数 14295
作品 0
杭州
手把手教你写电商爬虫-第四课 淘宝网商品爬虫自动JS渲染

系列教程: 手把手教你写电商爬虫-第一课 找个软柿子捏捏 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取 老规矩,...

游牧民族
2016/05/16
140
0
手把手教你写电商爬虫-第五课 京东商品评论爬虫 一起来对付反爬虫

系列教程: 手把手教你写电商爬虫-第一课 找个软柿子捏捏 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取 手把手教...

游牧民族
2016/05/16
204
0
互联网金融爬虫怎么写-第一课 p2p网贷爬虫(XPath入门)

相关教程: 手把手教你写电商爬虫-第一课 找个软柿子捏捏 手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫 手把手教你写电商爬虫-第三课 实战尚妆网AJAX请求处理和内容提取 手把手教...

游牧民族
2016/05/21
255
0
手把手教你写电商爬虫-第二课 实战尚妆网分页商品采集爬虫

系列教程 手把手教你写电商爬虫-第一课 找个软柿子捏捏 如果没有看过第一课的朋友,请先移步第一课,第一课讲了一些基础性的东西,通过软柿子"切糕王子"这个电商网站好好的练了一次手,相信大...

游牧民族
2016/05/12
166
0
互联网金融爬虫怎么写-第四课 雪球网股票爬虫(单页面多数据)

Previous on 系列教程: 互联网金融爬虫怎么写-第一课 p2p网贷爬虫(XPath入门) 互联网金融爬虫怎么写-第二课 雪球网股票爬虫(正则表达式入门) 互联网金融爬虫怎么写-第三课 雪球网股票...

游牧民族
2016/07/29
175
0
一个月入门Python爬虫,快速获取大规模数据

数据是创造和决策的原材料,高质量的数据都价值不菲。而利用爬虫,我们可以获取大量的价值数据,经分析可以发挥巨大的价值,比如: 豆瓣、知乎:爬取优质答案,筛选出各话题下热门内容,探索...

Python开发者
04/25
0
0
WEB前端工程师-练成

一、HTML和CSS基础 1.1 开发工具 1.1.1 前端开发工具技巧介绍-DW篇 1.1.2 前端开发工具技巧介绍-Sublime篇 1.2 HTML和CSS基础课程 1.2.1 HTML+CSS基础课程 1.3 网页布局 1.3.1 如何用CSS进行...

霞女
2015/12/02
62
0
R语言爬虫系列6|动态数据抓取范例

感谢关注天善智能,走好数据之路↑↑↑ 欢迎关注天善智能,我们是专注于商业智能BI,人工智能AI,大数据分析与挖掘领域的垂直社区,学习,问答、求职一站式搞定! 本文作者:天善智能社区专家...

天善智能
2017/11/27
0
0
大数据开发学习的内容介绍,成都大数据培训机构哪里好?

大数据开发培训已经成为了越来越多人的选择,大数据开发工程师也是各公司争相争夺的金领人才之一了,在当今科技发展非常迅速的社会里,越来越多人把职业规划投向了大数据开发。这里为大家整理...

加米谷大数据
昨天
0
0
好文章 - 收藏集 - 掘金

React Native 开发技术周报 (第九期)~ 官方教程, Native 和 JavaScript 通信机制, 分包实践等等应有尽有~ - 前端 - 掘金 尊重版权,未经授权不得转载出处:http://www.lcode.org 本周报来自江清...

掘金官方
2017/07/12
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

社交系统ThinkSNS+ V1.8.3更新播报

     研发发布版本号:1.8.3   本次版本于2018年7月16日发布   本次发布类型:新增功能、细节调整与优化   社交系统ThinkSNSPlus更新体验:请于官网下载/安装最新版或联系QQ35159...

ThinkSNS账号
2分钟前
0
0
教育思考:选择编程是一场父母和孩子的和解[图]

教育思考:选择编程是一场父母和孩子的和解[图]: 之前有个很热的段子是这样讲的:深夜十点的时候,某小区一女子大声喊叫“什么关系?啊?!到底什么关系?你说!”最后发现原来是一位妈妈陪...

原创小博客
2分钟前
0
0
X64汇编之指令格式解析

最近由于项目组内要做特征码搜索的东西,便于去Hook一些未导出函数,你懂得...于是就闲着学习了一下x86/x64的汇编指令格式。x86的汇编指令格式请参照http://bbs.pediy.com/showthread.php?t...

simpower
5分钟前
0
0
rust 语法概要(只适合不熟悉时快速查阅使用,不适合理解其精髓。未完待续)

注意:本内容只适合快查,不适合理解精髓。精髓请研读 https://kaisery.github.io/trpl-zh-cn/foreword.html 基本数据类型 i8,i16,i32,i64,i128 u8,u16,u32,u64,u128 f32,f64 char bool:true...

捍卫机密
8分钟前
0
0
JS中严格模式和非严格模式

1,使用 严格模式的使用很简单,只有在代码首部加入字符串 "use strict"。必须在首部即首部指其前面没有任何有效js代码除注释,否则无效 2.注意事项 (1)不使用var声明变量严格模式中将不通...

AndyZhouX
8分钟前
0
0
Nginx配置error_page 404 500等自定义的错误页面

Nginx 做web server时, 开发中发现有时候的网站代码有错误,我们需要跳转到一个指定内容的错误页面: 1. 在nginx.conf配置文件上加上一句: fastcgi_intercept_errors on; 2. 服务中加上: er...

MichaelShu
11分钟前
0
0
微服务架构下的监控系统设计(一)——指标数据的采集展示

前言 微服务是一种架构风格,一个大型复杂软件应用通常由多个微服务组成。系统中的各个微服务可被独立部署,各个微服务之间是松耦合的。每个微服务仅关注于完成一件任务并很好地完成该任务。...

UCloudTech
16分钟前
0
0
极客时间《趣谈网络协议》之开篇词学习笔记

出于个人兴趣,本人在极客时间购买了网易研究院云计算技术部的首席架构师刘超老师关于计算机网络的专栏之《趣谈网络协议》,由于知识版权原因,不能直接分享刘超老师的原文,所以,我会在每次...

aibinxiao
18分钟前
1
0
Activiti - 新一代的开源 BPM 引擎

Activiti 背景简介、服务和功能介绍 董 娜, 狄 浩, 和 张 晓篱 2012 年 7 月 23 日发布 背景介绍 Activiti 其核心是 BPMN 2.0 的流程引擎。BPMN 是目前被各 BPM 厂商广泛接受的 BPM 标准,全...

孟飞阳
24分钟前
0
0
最有效的方式来适配

最有效的方式来进行屏幕适配 在上代码之前先把屏幕相关的几个概念搞清楚:Density、DensityDpi、ScaleDensity。这里我们不过多讲解这些概念知识。 1.0 获取设计图的屏幕尺寸:这里我以360dp...

android-key
26分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部