Парсинг данных о товарах электронной торговли
В этом уроке мы рассмотрим, как извлекать данные о товарах с любых сайтов электронной коммерции с помощью Java. Существует множество различных вариантов использования извлечения данных о товарах, таких как:
- Мониторинг цен в электронной коммерции
- Сравнение цен
- Мониторинг доступности
- Извлечение отзывов
- Исследование рынка
- Нарушение MAP
Что вам понадобится
Мы будем использовать HtmlUnit для выполнения HTTP-запроса и разбора DOM. Добавьте эту зависимость в pom.xml.
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.19</version>
</dependency>
Мы также будем использовать библиотеку Jackson:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.9.8</version>
</dependency>
Schema.org
Для того чтобы извлечь интересующие нас поля, мы будем анализировать метаданные https://schema.org из разметки Html.
Schema - это семантический словарь, который может быть добавлен к любой веб-странице. Внедрение Schema имеет множество преимуществ. Большинство поисковых систем используют ее, чтобы понять, о чем страница (продукт, статья, отзыв и многое другое).
По данным schema.org, во всем мире ее используют около 10 млн. сайтов. Это очень много! Существуют различные типы Schema, и сегодня мы рассмотрим тип Product.
Это очень удобно, потому что если вы написали парсер, который извлекает определенные данные из схемы, то он будет работать на любом другом сайте, использующем ту же схему. Больше не нужно писать специфические XPath / CSS-селекторы!
Существует три основных вида разметки schema:
JSON-LD
<script type="application/ld+json">
{
"@context": "http://schema.org",
"@type": "ItemList",
"url": "http://multivarki.ru?filters%5Bprice%5D%5BLTE%5D=39600",
"numberOfItems": "315",
"itemListElement": [
{
"@type": "Product",
"image": "http://img01.multivarki.ru.ru/c9/f1/a5fe6642-18d0-47ad-b038-6fca20f1c923.jpeg",
"url": "http://multivarki.ru/brand_502/",
"name": "Brand 502",
"offers": {
"@type": "Offer",
"price": "4399 p."
}
},
{
"@type": "Product",
"name": "..."
}
]
}
</script>
RDF-A
<div vocab="http://schema.org/" typeof="ItemList">
<link property="url" href="http://multivarki.ru?filters%5Bprice%5D%5BLTE%5D=39600"><span property="numberOfItems">315</span>
<div property="itemListElement" typeof="Product">
<img property="image" alt="Photo of product" src="http://img01.multivarki.ru.ru/c9/f1/a5fe6642-18d0-47ad-b038-6fca20f1c923.jpeg"> <a property="url" href="http://multivarki.ru/brand_502/"><span property="name">BRAND 502</span></a>
<div property="offers" typeof="http://schema.org/Offer">
<meta property="schema:priceCurrency" content="RUB">руб
<meta property="schema:price" content="4399.00">4 399,00
<link property="schema:itemCondition" href="http://schema.org/NewCondition">
</div>...
<div property="itemListElement" typeof="Product">
...
</div>
</div>
</div>
И тот, который используется в нашем примере, - Microdata:
<div class="schema-org">
<div itemscope="" itemtype="https://schema.org/Product">
<img itemprop="image" src="https://images.asos-media.com/products/the-north-face-vault-backpack-28-litres-in-black/10253008-1-black" alt="Image 1 of The North Face Vault Backpack 28 Litres in Black">
<link itemprop="itemCondition" href="https://schema.org/NewCondition">
<span itemprop="productID">10253008</span>
<span itemprop="sku">10253008</span>
<span itemprop="brand" itemscope="" itemtype="https://schema.org/Brand">
<span itemprop="name">The North Face</span>
</span>
<span itemprop="name">The North Face Vault Backpack 28 Litres in Black</span>
<span itemprop="description">Shop The North Face Vault Backpack 28 Litres in Black at ASOS. Discover fashion online.</span>
<span itemprop="offers" itemscope="" itemtype="https://schema.org/Offer">
<link itemprop="availability" href="https://schema.org/InStock">
<meta itemprop="priceCurrency" content="GBP">
<span itemprop="price">60</span>
<span itemprop="eligibleRegion">GB</span>
<span itemprop="seller" itemscope="" itemtype="https://schema.org/Organization">
<span itemprop="name">ASOS</span>
</span>
</span>
</div></div>
Обратите внимание, что на одной странице можно разместить несколько предложений.
Для более подробного изучения рекомендуем ознакомиться с руководством по веб-парсингу.

Извлечение данных
public class Product {private BigDecimal price;private String name;private String sku;private URL imageUrl;private String currency;// ...геттеры и сеттеры
WebClient client = new WebClient();client.getOptions().setCssEnabled(false);client.getOptions().setJavaScriptEnabled(false);String productUrl = "https://www.asos.com/the-north-face/the-north-face-vault-backpack-28-litres-in-black/prd/10253008";HtmlPage page = client.getPage(productUrl);HtmlElement productNode = ((HtmlElement) page.getFirstByXPath("/*[@itemtype='https://schema.org/Product']"));URL imageUrl = new URL((((HtmlElement) productNode.getFirstByXPath("./img"))).getAttribute("src"));HtmlElement offers = ((HtmlElement) productNode.getFirstByXPath("./span[@itemprop='offers']"));BigDecimal price = new BigDecimal(((HtmlElement) offers.getFirstByXPath("./span[@itemprop='price']")).asText());String productName = (((HtmlElement) productNode


