Всем привет.
История эта случилась из-за экономии. При покупке платного аккаунта мы даже не обратили внимание на то, сколько полезного даёт тариф Эксперт.
Ах, если бы мы обратили на это внимание, то мне не пришлось бы осваивать Selenium и основы Java.
Как-то раз возникла маркетинговая задача — собрать контакты закупщиков в компаниях по нашей тематике.
Ищу все конкурсы, подходящие по ключевым словам и в нужных регионах. За все прошлые годы, завершенные и текущие.
В выгрузке на тарифе Стандарт вот такие данные:
Есть только название компании. Контактных данных закупщика нет.
Теперь, чтобы не собирать вручную контактные данные закупщика, принимаю решение писать скрипт.
Так как у Контур.Закупок вся страничка загружается javascript-ом, то простым парсингом тут не отделаешься. Придётся писать скрипт на Selenium.
Для начала подготовим исходные данные — сохраняем в CSV номер конкурса (он же параметр в URL), а также название компании, чтобы не парсить её. Всё это в файл kontur_getContacts_src.csv
Далее, скрипт на Java с комментариями
Запускаем скрипт Selenium
Результатом будет вот такой файл с контактами, который можно использовать в маркетинговых целях.
История эта случилась из-за экономии. При покупке платного аккаунта мы даже не обратили внимание на то, сколько полезного даёт тариф Эксперт.
Ах, если бы мы обратили на это внимание, то мне не пришлось бы осваивать Selenium и основы Java.
Как-то раз возникла маркетинговая задача — собрать контакты закупщиков в компаниях по нашей тематике.
Ищу все конкурсы, подходящие по ключевым словам и в нужных регионах. За все прошлые годы, завершенные и текущие.
В выгрузке на тарифе Стандарт вот такие данные:
Есть только название компании. Контактных данных закупщика нет.
Теперь, чтобы не собирать вручную контактные данные закупщика, принимаю решение писать скрипт.
Так как у Контур.Закупок вся страничка загружается javascript-ом, то простым парсингом тут не отделаешься. Придётся писать скрипт на Selenium.
Для начала подготовим исходные данные — сохраняем в CSV номер конкурса (он же параметр в URL), а также название компании, чтобы не парсить её. Всё это в файл kontur_getContacts_src.csv
Далее, скрипт на Java с комментариями
import org.openqa.selenium.By;
import org.openqa.selenium.firefox.FirefoxDriver;
import org.openqa.selenium.*;
import org.openqa.selenium.firefox.*;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.WebElement;
import org.openqa.selenium.support.ui.Select;
import org.openqa.selenium.support.ui.ExpectedCondition;
import org.openqa.selenium.support.ui.WebDriverWait;
import org.openqa.selenium.remote.DesiredCapabilities;
import org.openqa.selenium.remote.RemoteWebDriver;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.io.*;
import java.nio.file.*;
public class kontur_getContacts{
public static void main(String args[]) throws Exception{
//Запускаем коннектор к FireFox
System.setProperty("webdriver.gecko.driver", "geckodriver.exe");
FirefoxDriver driver = new FirefoxDriver();// Create a Firefox browser instance
driver.manage().timeouts().implicitlyWait(10, TimeUnit.SECONDS);
// Логинимся в Контур.Закупки
driver.get("https://auth.kontur.ru/login.aspx?authmode=certlogin&back=https%3A%2F%2Fzakupki.kontur.ru%2FLogin%2FCallback%3FReturnUrl%3Dhttps%253A%252F%252Fzakupki.kontur.ru%252F%253Fevent-login%253D1&customize=zakupki"); //Открываем страничку логина
Thread.sleep(2*1000);
WebElement login_field = driver.findElement(By.cssSelector(".loginPassword__login input")); // Ищем поле логин
login_field.sendKeys("sales@mycomp.ru");//Посылаем текст элементу логин
WebElement pass_field = driver.findElement(By.cssSelector("input.input__realInput")); //Ищем поле Пароль
pass_field.sendKeys("password");//Посылаем текст элементу пароль
Thread.sleep(1*1000); //Жду
driver.findElement(By.cssSelector("input.button__input")).click(); // Ставлю галочку Оставаться в системе
Thread.sleep(1*1000); //Жду
driver.findElement(By.cssSelector(".loginPassword__submit .button__input")).click(); //Отправляю форму
Thread.sleep(2*1000); //Жду
String sourceFilePath = "C:/Users/user/selenium/kontur_getContacts_src.csv";//Файл, откуда брать исходную информацию
String resultFilePath = "C:/Users/user/selenium/kontur_getContacts_result.csv";//Файл, куда писать результаты
String delimeter = ";"; // Разделитель в файле с исходной информацией
//Объявляем переменные
String name; String text;
Integer flag_hasName=0;
Integer flag_oneVar=0;
try{
//Откроем файл с проектами
FileInputStream fstream = new FileInputStream(sourceFilePath);
BufferedReader br = new BufferedReader(new InputStreamReader(fstream));
String strLine;//Объявляем переменные
String[] subStr;//Объявляем переменные
//Очищаем результирующий файл
byte[] myBytes = "".getBytes();
Files.write(Paths.get(resultFilePath), myBytes);
while ((strLine = br.readLine()) != null){ //Читаем файл с исходными данными построчно
System.out.println(strLine); //Смотрим в консоли текущуб строку
//Делим текущую строку по делимитеру
subStr = strLine.split(delimeter);
System.out.println("Found order_id "+subStr[0]+" and Organization is "+subStr[1]);
//Открываем страничку с этой закупкой
driver.get("https://zakupki.kontur.ru/"+subStr[0]);
/* Находим первую ссылочку на контакт закупщика */
name =""; //Очищаем переменную, в кот будет имя заказчика
text =""; //Очищаем переменную, в кот будут результаты работы скрипта
List<WebElement> tenderField_data_in=driver.findElements(By.cssSelector(".popup__mainContacts .tenderField__s div.tenderField_data_in")); //Находим первую ссылку
if(tenderField_data_in.size()>0){
WebElement man = driver.findElement(By.cssSelector(".popup__mainContacts .tenderField__s div.tenderField_data_in"));//Находим поле имя
System.out.println("FOUND is "+man.getAttribute("textContent")); //Смотрим имя в консоли
name = man.getAttribute("textContent").trim(); //Присваиваем имя переменной name
}
// Ищем ссылки с данными заказчика
List<WebElement> elements = driver.findElements(By.cssSelector(".tenderField .tenderField_data_in a"));
System.out.println("Count elements in array is "+elements.size()); //Смотрим в консоли количество найденных элементов данных
if(elements.size()>0){ //Есть линки на странице
WebElement email = driver.findElement(By.cssSelector(".tenderField .tenderField_data_in a")); //Выделяем емейл
text=subStr[1]+delimeter+email.getAttribute("href")+delimeter+name+"\r\n"; // Формируем строку для записи в файл с результатами
Files.write(Paths.get(resultFilePath), text.getBytes(), StandardOpenOption.APPEND); //Дописываем в файл
}
}
}catch (IOException e){
System.out.println("Error opening or processing file with finished purchases");
}
// Close the browser instance
driver.quit();
}
}
Запускаем скрипт Selenium
C:\Users\user\selenium>"C:\Program Files\Java\jdk-10.0.1\bin\javac" -cp selenium-server-standalone-3.13.0.jar; kontur_getContacts.java
* C:\Users\user\selenium>"C:\Program Files\Java\jre-10.0.1\bin\java" -cp selenium-server-standalone-3.13.0.jar; kontur_getContacts
Результатом будет вот такой файл с контактами, который можно использовать в маркетинговых целях.
saw_tooth
Есть же wait for!
iTarakan Автор
Это мой первый скрипт на Java. Я вообще то PHP-шник. А Java я гуглю и пишу. Соответственно, что первое попалось, то и пишу.
saw_tooth
Понял.
iTarakan Автор
Решить то можно и без Seleniuma. Ну я решил вот так сделать, и, может быть, это кому то будет полезным готовым скриптом по работе с Контуром.
А по поводу «Thread.sleep(2*1000);» — я руководствовался тем, что не знаю систему безопасности в Контуре, поэтому, чтобы не забанили аккаунт, притворялся простым юзером, который вводит данные с паузами. Паузу оно делает, поэтому задачу свою выполняет. Если что-то не нравится в написании, тут каждый может что-то добавить, что-то убрать.
Light_Metal
shirase55
Зачем такие сложности. Посмотреть в devtools ajax запрос и повторить его. Если защиты нет то это 10 минут работы.
iTarakan Автор
1. Я не нашёл, где они в ajax-запросах. Может быть плохо искал, но…
2. К тому же там ещё сложность в посылке логина системе. Страничка логина не простая, а защищённая. Вот из-за него и пришлось работать из браузера.
saw_tooth
Самая обычная
iTarakan Автор
Ну да, вижу, что у Вас получилось отловить этот ajax.
saw_tooth
В dev-tool браузера, на вкладке Network, есть волшебная галочка Preserve Log.
iTarakan Автор
Я тоже теперь вижу этот запрос. Спасибо, полезно!