提交 15724fe1 authored 作者: 梁业锦's avatar 梁业锦 💬

增加了Pull And Bear的爬虫

上级 a0445920
......@@ -25,7 +25,7 @@
### Pull and Bear
- 主页:https://www.pullandbear.cn/cn/%E5%A5%B3%E5%A3%AB-c1030204574.html
- 命名:pullandbear
- 爬虫进度:存在缺陷
- 爬虫进度:**已完成**
- 有反爬机制,有时会直接失效,不稳定
### Gap
- 主页:https://www.gap.cn/
......@@ -38,9 +38,9 @@
### Uniqlo
- 主页:https://www.uniqlo.cn/UNIQLO_U19FW_MEN.html
- 命名:uniqlo
- 爬虫进度:存在缺陷--
- 图片:会直接下载
- 无法获取折扣后的价格
- 爬虫进度:**已完成**
- 可能存在的缺陷:
- 图片的路径是直接下载图片
### Nike
- 主页:https://www.nike.com/cn
- 命名:nike
......@@ -53,7 +53,7 @@
- 主页:https://www2.hm.com/zh_cn/
- 命名:hm
- 爬虫进度:已能获取到数据
- 图片路径处理难度太多
- Json被做了一些难处理的封装,现有工具无法将其转换为Json格式
- 商品颜色通过商品详情页的url来区分,暂未找到规律
### LiLy
- 主页:http://www.lily.sh.cn/webapp/wcs/stores/servlet/lilystore
......@@ -102,11 +102,22 @@
- 数据来源
- 商品详情:https://www.massimodutti.cn/cn/%E5%A5%B3%E8%A3%85/%E7%B3%BB%E5%88%97/%E8%A1%AC%E8%A1%AB%E5%92%8C%E7%BD%A9%E8%A1%AB/%E8%A1%AC%E8%A1%AB/%E6%BB%91%E9%9B%AA%E9%A3%8E%E7%B3%BB%E5%88%97%E9%A5%B0%E5%8F%A3%E8%A2%8B%E8%A1%AC%E8%A1%AB-c1718602p8730105.html?colorId=420&categoryId=1718602
- 数据接口:https://www.massimodutti.cn/itxrest/2/catalog/store/35009478/30359500/category/0/product/8730105/detail?languageId=-7&appId=1
### COACH
- 主页:https://china.coach.com/women.html
- 命名:coach
- 爬虫进度:
### Revolve
- 主页:https://www.revolve.com/wrangler/br/57f1a1/?utm_source=baidu&utm_medium=cpc&utm_campaign=intl_P_cn-d-Wrangler
- 命名:reolve
- 爬虫进度:
### Vans
- 主页:https://vans.com.cn/gallery-index---0---36.html
- 命名:Vans
### 待选爬虫网站:
- 18,https://www.massimodutti.cn/cn/男装/季末折扣/休闲西装-c1745921.html ( 西班牙品牌)
- 19,https://china.coach.com/women.html
- 20,https://www.revolve.com/wrangler/br/57f1a1/?utm_source=baidu&utm_medium=cpc&utm_campaign=intl_P_cn-d-Wrangler (美国轻奢品牌集合网站)
- 21,https://vans.com.cn/gallery-index---0---36.html
- 22,https://zarahome.tmall.com/?spm=a1z10.3-b-s.1997427721.d4918089.7b872e00zWrHhi
- 23,https://oysho.tmall.com/ (SPORT WEAR)
......@@ -124,6 +135,13 @@
## 爬虫Json数据返回规范
### 封装类 [ProductResponse](../src/main/java/com/diaoyun/zion/chinafrica/vo/ProductResponse.java)
封装类的属性已经说明了爬虫需要爬取的数据有哪一些
- skuId 标识规范:;[颜色id];[尺寸id];
- 该 id 通过爬取**颜色****尺寸**对应数据时获取到的唯一标识
- 用于标识**库存****价格**
#### 按照 Nike 爬虫返回的数据进行封装
│── data 数据<br>
│ │── dynStock 库存<br>
......
......@@ -2,7 +2,10 @@ package com.diaoyun.zion.chinafrica.bis.impl;
import com.diaoyun.zion.chinafrica.bis.IItemSpider;
import com.diaoyun.zion.chinafrica.enums.PlatformEnum;
import com.diaoyun.zion.chinafrica.vo.ProductResponse;
import com.diaoyun.zion.master.util.HttpClientUtil;
import com.diaoyun.zion.master.util.SpiderUtil;
import com.diaoyun.zion.master.util.TranslateHelper;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.slf4j.Logger;
......@@ -15,8 +18,9 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeoutException;
/**
* 西班牙年轻时尚品牌-pullandbear 数据爬虫
* 西班牙年轻时尚品牌-PullAndBear 数据爬虫
*
* @author 爱酱油不爱醋
*/
@Component("pullandbearSpider")
public class PullandbearSpider implements IItemSpider {
......@@ -24,20 +28,27 @@ public class PullandbearSpider implements IItemSpider {
private static Logger logger = LoggerFactory.getLogger(PullandbearSpider.class);
/**
* Pull and Bear 商品详情链接
* PullAndBear 商品详情链接
*/
private static final String PULL_AND_BEAR_URL="https://www.pullandbear.cn/itxrest/2/catalog/store/24009528/20309423/category/0/product/";
/**
* PullAndBear 数据爬虫
* @see com.diaoyun.zion.chinafrica.service.impl.SpiderServiceImpl#judgeUrlType 修改商品详情页路径
* @see SpiderUtil#formatPullAndBearProductResponse 格式化数据方法
* @param targetUrl 接收的商品详情路径
* @return 格式化与翻译后的 Json 数据
*/
@Override
public JSONObject captureItem(String targetUrl) throws URISyntaxException, IOException, ExecutionException, InterruptedException, TimeoutException {
// 提取链接中的商品 id 信息
String pId = targetUrl.substring(targetUrl.lastIndexOf("p")+1, targetUrl.lastIndexOf(".html"));
// 组成链接并获取商品详情信息的 Json
targetUrl = PULL_AND_BEAR_URL + pId + "/detail?languageId=-7&appId=1";
// 获取网页内容
String content = HttpClientUtil.getContentByUrl(targetUrl, PlatformEnum.PULLANDBEAR.getValue());
// 转换为Json格式
JSONObject resultJson = JSONObject.fromObject(content);
ProductResponse productResponse = SpiderUtil.formatPullAndBearProductResponse(resultJson, pId);
resultJson = JSONObject.fromObject(productResponse);
// 翻译
TranslateHelper.translateProductResponse(resultJson);
return resultJson;
}
......
......@@ -34,6 +34,7 @@ public class UniqloSpider implements IItemSpider {
/**
* Uniqlo 数据爬虫
* @see com.diaoyun.zion.chinafrica.service.impl.SpiderServiceImpl#judgeUrlType 修改商品详情页路径
* @see
* @see SpiderUtil#formatUniqloProductResponse 格式化数据方法
* @param targetUrl 接收的商品详情路径
* @return 格式化与翻译后的 Json 数据
......@@ -57,14 +58,4 @@ public class UniqloSpider implements IItemSpider {
return resultJson;
}
public static void main(String[] args) throws Exception {
String targetUrl = "https://www.uniqlo.cn/product-detail.html?productCode=u0000000001970";
// 截取链接中的商品 id
String[] split = targetUrl.split("productCode=");
String pId = split[1];
targetUrl = UNIQLO_URL + "zh_CN/" + pId + ".json";
String content = HttpClientUtil.getContentByUrl(targetUrl, PlatformEnum.UNIQLO.getValue());
System.out.println(content);
}
}
......@@ -150,22 +150,6 @@ public class JsoupUtil {
}
}
public static void main(String[] args) throws Exception {
String targetUrl = "https://www2.hm.com/zh_cn/productpage.0809313001.html";
String content = HttpClientUtil.getContentByUrl(targetUrl, PlatformEnum.HM.getValue());
String detailStr = getScriptContent(content, "productArticleDetails");
int firstBrackets=detailStr.indexOf("{");
int lastbrackets=detailStr.lastIndexOf("}");
String resultStr = detailStr.substring(firstBrackets,lastbrackets+1);
int firstImage = detailStr.indexOf("'images':[");
int lastImage = detailStr.lastIndexOf("'video':");
detailStr = detailStr.substring(firstImage, lastImage);
resultStr = resultStr.replace(detailStr, "");
JSONObject resultObj = JSONObject.fromObject(resultStr);
System.out.println(resultObj);
}
/**
* 解析出商品详情
*
......@@ -260,6 +244,40 @@ public class JsoupUtil {
return dataMap;
}
/**
* 获取 H&M 爬虫的主要数据
* @param content
* @throws Exception
*/
public static JSONObject getHMJsonData(String content) {
String detailStr = getScriptContent(content, "productArticleDetails");
int firstBrackets=detailStr.indexOf("{");
int lastbrackets=detailStr.lastIndexOf("}");
String resultStr = detailStr.substring(firstBrackets,lastbrackets+1);
int firstImage = detailStr.indexOf("'images':[");
int lastImage = detailStr.lastIndexOf("'video':");
detailStr = detailStr.substring(firstImage, lastImage);
resultStr = resultStr.replace(detailStr, "");
JSONObject resultObj = JSONObject.fromObject(resultStr);
return resultObj;
}
public static void main(String[] args) throws Exception {
String targetUrl = "https://www2.hm.com/zh_cn/productpage.0754698003.html";
String content = HttpClientUtil.getContentByUrl(targetUrl, PlatformEnum.ZARA.getValue());
String detailStr = getScriptContent(content, "productArticleDetails");
int firstBrackets=detailStr.indexOf("{");
int lastbrackets=detailStr.lastIndexOf("}");
String resultStr = detailStr.substring(firstBrackets,lastbrackets+1);
resultStr = resultStr.replace("isDesktop ? ", "");
String regexp = "\'";
resultStr = resultStr.replaceAll(regexp, "\"");
JSONObject resultObj = JSONObject.fromObject(resultStr);
System.err.println(resultObj);
}
/**
* 根据script id获取内容
* @param content
......
......@@ -5,6 +5,7 @@ import com.diaoyun.zion.chinafrica.entity.TbCfFeeEntity;
import com.diaoyun.zion.chinafrica.enums.PlatformEnum;
import com.diaoyun.zion.chinafrica.service.TbCfFeeService;
import com.diaoyun.zion.chinafrica.vo.*;
import com.stripe.model.Product;
import net.sf.json.JSONArray;
import net.sf.json.JSONObject;
import org.apache.commons.lang3.StringUtils;
......@@ -827,4 +828,180 @@ public class SpiderUtil {
return productResponse;
}
/**
* 格式化 PullAndBear 返回数据
* @see com.diaoyun.zion.chinafrica.bis.impl.PullandbearSpider
* @param dataMap 主要的 json 数据
* @param pId 商品链接的 id
* @return 格式化后的数据
*/
public static ProductResponse formatPullAndBearProductResponse(JSONObject dataMap, String pId) {
// 声明封装类
ProductResponse productResponse = new ProductResponse();
// 属性:Zara 的商品属性有颜色、尺码
Map<String, Set<ProductProp>> productPropSet = new HashMap<>(16);
// 原始价
List<OriginalPrice> originalPriceList = new ArrayList<>();
// 促销价格
List<ProductPromotion> promotionList = new ArrayList<>();
// 库存
DynStock dynStock = new DynStock();
// 其实数据没有包含确切的库存数,这里默认给足量的库存
dynStock.setSellableQuantity(9999);
// 商品基本信息
ItemInfo itemInfo = new ItemInfo();
// 取 bundleProductSummaries 的节点对象
JSONObject bundleProductSummariesObj = dataMap.getJSONArray("bundleProductSummaries").getJSONObject(0);
//////////////////////////////////// 获取商品基本信息 ////////////////////////////////////////////
itemInfo.setShopName(PlatformEnum.PULLANDBEAR.getLabel());
itemInfo.setShopUrl("https://www.pullandbear.cn/cn/");
itemInfo.setItemId(pId);
itemInfo.setTitle(bundleProductSummariesObj.getString("name"));
//////////////////////////////////// 获取商品基本信息End(图片下取) ////////////////////////////////////////////
// 取 colors 数组节点
JSONArray colorsArr = bundleProductSummariesObj.getJSONObject("detail").getJSONArray("colors");
for (int i = 0; i < colorsArr.size(); i++) {
JSONObject colorsObj = colorsArr.getJSONObject(i);
//////////////////////////////////// 获取商品颜色与图片属性 ////////////////////////////////////////////
Set<ProductProp> propSetColor = new HashSet<>(16);
ProductProp productPropColor = new ProductProp();
// 颜色id
String colorNo = colorsObj.getString("id");
productPropColor.setPropId(colorNo);
// 颜色名
String colorName = colorsObj.getString("name");
productPropColor.setPropName(colorName);
// 取 image 对象节点
JSONObject imageObj = colorsObj.getJSONObject("image");
// 颜色图片
String imageUrl = "https://static.pullandbear.cn/2/photos/"
+ imageObj.getString("url")
+ "_2_1_8.jpg?t="
+ imageObj.getString("timestamp");
productPropColor.setImage(imageUrl);
if (i == 0) {
itemInfo.setPic(imageUrl);
}
propSetColor.add(productPropColor);
if (productPropSet.get("颜色") == null) {
productPropSet.put("颜色", propSetColor);
} else {
Set<ProductProp> oldPropSet = productPropSet.get("颜色");
propSetColor.addAll(oldPropSet);
productPropSet.put("颜色", propSetColor);
}
//////////////////////////////////// 获取商品颜色与图片属性 END ////////////////////////////////////////////
// 取 siezes 对象数组
JSONArray sizesArr = colorsObj.getJSONArray("sizes");
for (int j = 0; j < sizesArr.size(); j++) {
JSONObject sizesObj = sizesArr.getJSONObject(j);
///////////////////////// 获取商品尺码属性 ////////////////////
Set<ProductProp> sizePropSetSize = new HashSet<>();
ProductProp productPropSize = new ProductProp();
String size = sizesObj.getString("name");
productPropSize.setPropName(size);
String sizeNo = sizesObj.getString("sku");
productPropSize.setPropId(sizeNo);
sizePropSetSize.add(productPropSize);
if (productPropSet.get("尺码") == null) {
productPropSet.put("尺码", sizePropSetSize);
} else {
Set<ProductProp> oldPropSet = productPropSet.get("尺码");
sizePropSetSize.addAll(oldPropSet);
productPropSet.put("尺码", sizePropSetSize);
}
///////////////////////// 获取商品尺码属性 END////////////////////
// 商品的库存id
String skuStr = ";" + colorNo + ";" + sizeNo + ";";
//////////////////////////////////// 获取库存 ////////////////////////////////////////////
// 设置:商品包含库存信息
productResponse.setStockFlag(true);
List<ProductSkuStock> productSkuStockList = dynStock.getProductSkuStockList();
if (productSkuStockList == null) {
productSkuStockList = new ArrayList<>();
}
ProductSkuStock productSkuStock = new ProductSkuStock();
// 设置:可用库存值,PullAndBear 未有可用的库存数据
productSkuStock.setSellableQuantity(999);
// 设置:库存对应的id
productSkuStock.setSkuStr(skuStr);
productSkuStockList.add(productSkuStock);
dynStock.setProductSkuStockList(productSkuStockList);
//////////////////////////////////// 获取库存 END/////////////////////////////////////////
//////////////////////////////////// 获取原始价 //////////////////////////////////
OriginalPrice originalPrice = new OriginalPrice();
// 获取商品的原始价
String fullPrice = sizesObj.getString("price");
BigDecimal priceOld=new BigDecimal(fullPrice);
BigDecimal div = new BigDecimal("100");
BigDecimal priceNew = priceOld.divide(div, 2, BigDecimal.ROUND_DOWN);
// TODO 转换汇率,目前商品单位是人民币
fullPrice= exchangeRate(priceNew.toString());
originalPrice.setPrice(fullPrice);
productResponse.setPrice(fullPrice);
productResponse.setSalePrice(fullPrice + "-" + fullPrice);
originalPrice.setSkuStr(skuStr);
originalPriceList.add(originalPrice);
//////////////////////////////////// 获取原始价 END//////////////////////////////////
}
}
// 按照一下顺序进行 json 数据的填充
productResponse.setPropFlag(true);
productResponse.setProductPropSet(productPropSet);
productResponse.setPlatform(PlatformEnum.PULLANDBEAR.getValue());
productResponse.setPromotionList(promotionList);
productResponse.setOriginalPriceList(originalPriceList);
productResponse.setItemInfo(itemInfo);
productResponse.setDynStock(dynStock);
return productResponse;
}
/**
* 格式化 H&M 返回数据
* @see com.diaoyun.zion.chinafrica.bis.impl.HmSpider
* @param dataMap 主要的 json 数据
* @return 格式化后的数据
*/
public static ProductResponse formatHMProductResponse(JSONObject dataMap) {
// 声明封装类
ProductResponse productResponse = new ProductResponse();
// 属性:Zara 的商品属性有颜色、尺码
Map<String, Set<ProductProp>> productPropSet = new HashMap<>(16);
// 原始价
List<OriginalPrice> originalPriceList = new ArrayList<>();
// 促销价格
List<ProductPromotion> promotionList = new ArrayList<>();
// 库存
DynStock dynStock = new DynStock();
// 其实数据没有包含确切的库存数,这里默认给足量的库存
dynStock.setSellableQuantity(9999);
// 商品基本信息
ItemInfo itemInfo = new ItemInfo();
// 按照一下顺序进行 json 数据的填充
productResponse.setPropFlag(true);
productResponse.setProductPropSet(productPropSet);
productResponse.setPlatform(PlatformEnum.PULLANDBEAR.getValue());
productResponse.setPromotionList(promotionList);
productResponse.setOriginalPriceList(originalPriceList);
productResponse.setItemInfo(itemInfo);
productResponse.setDynStock(dynStock);
return productResponse;
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论