Как я угонял автомобили

Интро
Моя история такая же, как и у других сотен айтишников в Украине. Учился я в математическом классе, мою школу на протяжении многих лет окружают недостройки, которые в свое время были притонами. Дальше был физ-мат КПИ, на котором меня научили усердно загребать знания. Ну и классический поиск себя, начиная с середины университетской жизни...
Пробовал я работать в банках, в магазинах электроники и бытовой техники, обувных магазинах, страховании и еще многих местах. К счастью, мой стаж во всех этих отраслях ограничивался одним днем. Были в этой нестабильной череде опыта, и профессии приближенные к IT — php’шные конторки, в которых я окончательно понял, какой работы я не хочу.
Неизменным было то, что я постоянно учил что-то техническое. Сперва HTML, потом CSS, далее РНР, JS, а потом взялся за голову и со злости выучил Java SE. Последняя технология привела меня в ряды автоматизаторов web-приложений и понеслось...
Я показывал отличный результат, осваивал новые вершины, перенимал у своих опытных сотрудников профессиональные навыки, поднимался вверх по карьерной лестнице. И внезапно понял, что мои финансовые возможности не совпадают с желаниями, ведь я все так же как и тот маленький мальчик из математического класса, продолжал жить в районе, где трубы заводов заменяют достопримечательности, а все окружающее напоминает гетто после бомбардировки.
И тут подвернулось дело. Мне понадобились автомобили, много автомобилей! Автомобили всех популярных марок, а также все их модели... И все это нужно было оформить в структурированном виде.
Техническая часть вопроса
Сперва, прошелся по поиску и не нашел данных в удобном для меня виде. Сразу после этого начал просматривать англоязычные автомобильные сайты. Остановился на cars.com, там есть отличный блок, в котором можно искать новые машины. Проклацал я этот функционал и убедился, что список машин меня удовлетворяет. Ну а дальше дело техники...
Открываю эклипс, создаю новый проект с такими зависимостями в pom.xml:
<dependencies> <dependency> <groupid>org.seleniumhq.selenium</groupid> <artifactid>selenium-server</artifactid> <version>2.25.0</version> </dependency> <dependency> <groupid>javax.xml</groupid> <artifactid>jaxp-api</artifactid> <version>1.4.2</version> </dependency> <dependency> <groupid>org.testng</groupid> <artifactid>testng</artifactid> <version>6.1.1</version> <scope>test</scope> </dependency> </dependencies>
Selenium-server нужен для возможности взаимодействовать с web-интерфейсом через браузер, jaxp-api необходим для формирования
Далее по диагонали освежил jax-документацию в своей памяти и написал незамысловатый класс, который предназначен для занесения в конечный документ марок машин и их моделей.
public class Hijacker {
private DocumentBuilderFactory docFactory = null;
private DocumentBuilder docBuilder = null;
private Document document = null;
private Element rootEl = null;
private TransformerFactory transformerFactory = null;
private Transformer transformer = null;
private DOMSource source = null;
public Hijacker() {
docFactory = DocumentBuilderFactory.newInstance();
try {
docBuilder = docFactory.newDocumentBuilder();
} catch (ParserConfigurationException e) {
e.printStackTrace();
}
document = docBuilder.newDocument();
rootEl = document.createElement("cars");
document.appendChild(rootEl);
transformerFactory = TransformerFactory.newInstance();
try {
transformer = transformerFactory.newTransformer();
} catch (TransformerConfigurationException e) {
e.printStackTrace();
}
}
public void addEntity(String makeVal, String modelVal) {
if (modelVal.equals("All Models") || makeVal.equals("All Makes")) {
return;
} else {
Element brandEl = document.createElement("brand");
Attr make = document.createAttribute("make");
make.setValue(makeVal);
brandEl.setAttributeNode(make);
rootEl.appendChild(brandEl);
Element model = document.createElement("model");
model.setTextContent(modelVal);
brandEl.appendChild(model);
}
}
public void createReport() throws TransformerException {
source = new DOMSource(document);
StreamResult result = new StreamResult(new File("E:\\CarEntities.xml"));
transformer.transform(source, result);
}
}
Конструктор и два метода полностью решают вопрос работы с
public class Parser {
Hijacker extractor = new Hijacker();
@Test
public void parseCars()
throws InterruptedException, TransformerException {
WebDriver driver = new FirefoxDriver();
driver.get("http://www.cars.com");
WebElement makeEl = driver.findElement(By.<span></span>id("newMake"));
Select makeDropDown = new Select(makeEl);
List<webelement> makeList = makeDropDown.getOptions();
for (WebElement make : makeList) {
Thread.sleep(2000);
WebElement modelEl = driver.findElement(By.<span></span>id("newModel"));
Select modelDropDown = new Select(modelEl);
makeDropDown.selectByVisibleText(make.getText());
List<webelement> modelList = modelDropDown.getOptions();
for (WebElement carModel : modelList) {
extractor.addEntity(make.getText(), carModel.getText());
}
}
extractor.createReport();
driver.close();
}
}
В этом классе, пожалуй, следует обратить внимание только на строчку с приостановкой потока. В связи с тем, что в зависимости от того, какую марку автомобиля мы выбираем, подгружается список ее всех возможных моделей, что иногда может происходить медленнее, чем отрабатывает WebDriver.
В результате получаем документ с четкой структурой вида:
<brand make="Acura"> <model>TSX</model> </brand> <brand make="Acura"> <model>ZDX</model> </brand> <brand make="Aston Martin"> <model>DB9</model> </brand> <brand make="Aston Martin"> <model>DBS</model> </brand>
В заключение хочу сказать, что этот рассказ получился менее захватывающим, чем фильм «Угнать за 60 секунд», но для попытки скрестить технический материал и мой аутсорсинговый юмор — самое оно.
31 коментар
Підписатись на коментаріВідписатись від коментарів Коментарі можуть залишати тільки користувачі з підтвердженими акаунтами.