Создаем парсер на Java
Многие компании используют парсинг сайтов, чтобы агрегировать информацию из конкурентных ресурсов. Ее можно получить из HTML-кода веб-страниц. Но только не ту, которая находится в картинках или другом медийном контенте. В этом руководстве мы научимся парсить данные с помощью Java.
Обязательные условия
- Базовые знания Java;
- Основы XPath.
Инструменты
Вам потребуется Java 8 и браузер HtmlUnit
<dependency>
<groupId>net.sourceforge.htmlunit</groupId>
<artifactId>htmlunit</artifactId>
<version>2.19</version>
</dependency>
Если вы используете Eclipse, советую изменить максимальную длину в окне подробностей (при нажатии на вкладку «Переменные»), чтобы можно было видеть весь HTML-код веб-страницы.

Парсер на java: пример-получим данные из интернет-магазина
В примере парсинга сайта Java мы извлечем информацию с интернет-магазина. Соберем имена, цены, а также картинки и экспортируем их в формат JSON.
Сначала посмотрим, что происходит при поиске товара в магазине. Для этого откройте «Инструменты разработчика» в Chrome и перейдите на вкладку «Network»:

URL поиска:
https://newyork.craigslist.org/search/moa?is_paid=all&search_distance_type=mi&query=iphone+6s
Также можно использовать
https://newyork.craigslist.org/search/sss?sort=rel&query=iphone+6s
Теперь откройте среду разработки. Пришло время писать код. Для выполнения запроса в HtmlUnit нужен WebClient. Сначала нужно отключить JavaScript, так как в нашем примере он не нужен, и без него страница будет загружаться быстрее:
String searchQuery = "Iphone 6s" ;
WebClient client = new WebClient();
client.getOptions().setCssEnabled(false);
client.getOptions().setJavaScriptEnabled(false);
try {
String searchUrl = "https://newyork.craigslist.org/search/sss?sort=rel&query=" + URLEncoder.encode(searchQuery, "UTF-8");
HtmlPage page = client.getPage(searchUrl);
}catch(Exception e){
e.printStackTrace();
}
}
В объекте HtmlPage будет HTML-код, доступ к которому можно получить с помощью метода asXml(). Вытянем с сайта названия, изображения и цены. Для этого нужно внимательно просмотреть структуру DOM:

Для парсинга страниц сайта есть несколько способов выбрать тег HTML, используя HtmlUnit:
- getHtmlElementById(String id);
- getFirstByXPath(String Xpath)-getByXPath(String XPath), который возвращает список.
Поскольку мы не можем использовать ID, чтобы выбрать теги, нужно составить выражение Xpath.
XPath — это язык запросов для выбора элементов XML (в нашем случае HTML).
Сначала нужно выбрать все теги <p> с классом `result-info. Затем выполнить итерацию в списке, и для каждого предмета выбрать название, цену и URL, а также вывести на экран.
List<HtmlElement> items = (List<HtmlElement>) page.getByXPath("//p[@class='result-info']" ;
if(items.isEmpty()){
System.out.println("No items found !");
}else{
for(HtmlElement item : items){
HtmlAnchor itemAnchor = ((HtmlAnchor) htmlItem.getFirstByXPath(".//a"));
String itemName = itemAnchor.asText();
String itemUrl = itemAnchor.getHrefAttribute() ;
HtmlElement spanPrice =((HtmlElement) htmlItem.getFirstByXPath(".//span[@class='result-price']")) ;
// Возможно, что для товара не установлена цена
String itemPrice = spanPrice == null ? "no price" : spanPrice.asText() ;
System.out.println( String.format("Name : %s Url : %s Price : %s", itemName, itemPrice, itemUrl));
}
}
Затем сохраним данные в формате JSON, используя библиотеку Jackson. Для представления элементов, полученных при парсинге email адресов с сайта, нам понадобится POJO (объект языка Java).
Item.java
public class Item {
private String title ;
private BigDecimal price ;
private String url ;
// геттеры и сеттеры
}
Затем добавим это в файл pom.xml:
<dependency>
<groupId>com.fasterxml.jackson.core</groupId>
<artifactId>jackson-databind</artifactId>
<version>2.7.0</version>
</dependency>
Теперь нужно создать элемент, задать атрибуты, конвертировать в строку или файл JSON и немного адаптировать предыдущий код парсинга данных с сайта:
for(HtmlElement htmlItem : items){
HtmlAnchor itemAnchor = ((HtmlAnchor) htmlItem.getFirstByXPath(".//span[@class='txt']/span[@class='pl']/a"));
HtmlElement spanPrice = ((HtmlElement) htmlItem.getFirstByXPath(".//span[@class='txt']/span[@class='l2']/span[@class='price']")) ;
// Возможно, для товара не установлена цена, в этом случае мы обозначаем ее как 0.0
String itemPrice = spanPrice == null ? "0.0" : spanPrice.asText() ;
Item item = new Item();
item.setTitle(itemAnchor.asText());
item.setUrl( baseUrl +
itemAnchor.getHrefAttribute());
item.setPrice(new BigDecimal(itemPrice.replace("$", "")));
ObjectMapper mapper = new ObjectMapper();
String jsonString = mapper.writeValueAsString(item) ;
System.out.println(jsonString);
}
Не останавливайтесь
Этот пример парсинга другого сайта не идеален, многое можно улучшить:
- Поиск по городам;
- Обработка пагинации;
- Поиск по нескольким критериям.
Код примера находится здесь.