#python-3.x #file #selenium #automation
#python-3.x #файл #selenium #автоматизация
Вопрос:
Я использую selenium с python и пытаюсь автоматизировать задачу, которая требует от меня загрузки файла .csv в веб-приложение. Обычно я бы нашел элемент ввода [type=file] и отправку ключей (path_to_image).
Но в этом случае элемент отсутствует. Кнопки «Обзор» нет, вы можете только перетаскивать и только файл .csv.
Поле, в которое вы помещаете файл, представляет собой всего лишь div с некоторым текстом. Хотя есть 2 входных элемента, они имеют тип =»hidden» и не могут взаимодействовать.
Существует скрипт, в котором я могу видеть данные после того, как я вручную загрузил их.
Он содержится в переменной с именем MMContacts.
var MMContacts =
{
isDirty: false,
isFeatureEnabled: true,
isDisabled: false,
data: [],
И после определения некоторых функций.
Заканчивается:
$(MMContacts.init);
Мне было интересно, есть ли простой способ выполнить какой-нибудь Javascript, который позволил бы мне заполнить это поле данных в MMContacts, или единственный способ автоматизировать это — автоматизация графического интерфейса (я знаю только самые основы JS)
ОБНОВЛЕНИЕ: весь скрипт
MMToolbar.next = function()
{
$("#mm-form input[name=dirty]").val(MMContacts.isDirty);
if (MMContacts.isDirty)
{
var data = encodeURIComponent(JSON.stringify(MMContacts.data));
data = btoa(data);
$("#mm-form input[name=data]").val(data);
}
$("#mm-form").submit();
}
MMToolbar.prev = function()
{
// window.history.back();
window.location = "/mailmerge/settings?id=33053"
}
var MMContacts =
{
isDirty: false,
isFeatureEnabled: true,
isDisabled: false,
data: [],
init: function()
{
// arrange
MMContacts.uploader = $("#uploader");
MMContacts.grid = $("#grid");
MMContacts.stats = $("#stats");
MMContacts.dropzone = $("#uploader,#grid");
// prepare dropzone
MMContacts.dropzone.on("dragover", function(e) { e.preventDefault(); e.stopPropagation(); });
MMContacts.dropzone.on("dragenter", function(e) { e.preventDefault(); e.stopPropagation(); });
MMContacts.dropzone.on("drop", MMContacts.dropped);
// refresh
MMContacts.render();
},
render: function()
{
if (MMContacts.data.length == 0)
{
MMContacts.uploader.show();
MMContacts.grid.hide();
MMContacts.stats.html("");
}
else
{
MMContacts.uploader.hide();
MMContacts.grid.show();
MMContacts.refreshGrid();
MMContacts.stats.html("Loaded " MMContacts.data.length " records - drop new file to replace.");
}
},
dropped: function(e)
{
if (MMContacts.isDisabled)
return;
if (!e.originalEvent.dataTransfer)
return;
if (!e.originalEvent.dataTransfer.files.length)
return;
e.preventDefault();
e.stopPropagation();
var file = e.originalEvent.dataTransfer.files[0];
// make sure file format is correct
/*if (file.type != "text/csv")
{
var type = (file.type.indexOf("spreadsheet") > -1) ? "XLSX" : file.type;
alert("Contact list must be a (CSV) file.nnThe file you are uploading is of type (" type "). Please open the file in a spreadsheet software (Excel or Google Spreadsheet) and save it as a CSV file.");
return;
}*/
if (!file.name.endsWith(".csv"))
{
var type = (file.type.indexOf("spreadsheet") > -1) ? "XLSX" : file.type;
alert("Contact list must be a (CSV) file.nnThe file you are uploading is of type (" type "). Please open the file in a spreadsheet software (Excel or Google Spreadsheet) and save it as a CSV file.");
return;
}
// clean/trim file before processing
var reader = new FileReader();
reader.onloadend = function(event) {
var lines = event.target.result.trim().split("n");
var data = [];
for(var i = 0; i < lines.length; i )
{
var line = lines[i];
// skip if empty line
if (line.trim().length == 0) continue;
// skip if only commas
var clean = line.replace(/s /g, "");
if (clean.length == clean.split(",").length -1) continue;
data.push(line);
}
MMContacts.parseContent(data.join("n"));
}
reader.readAsText(file);
},
parseContent: function(data)
{
Papa.parse(data, {
header: true,
complete: function(results) {
// validate file is not empty
if (results.data.length < 0)
{
Modal.alert("The file you chose is empty.");
return;
}
// restrict non-premium users
if (!MMContacts.isFeatureEnabled amp;amp; results.data.length > 20)
{
$("#premium-notice").show();
return;
}
else
{
$("#premium-notice").hide();
}
// validate it's not too large
if (results.data.length > 200)
{
$("#limit-notice #limit-uploaded").html(results.data.length);
$("#limit-notice").show();
return;
}
else
{
$("#limit-notice").hide();
}
// confirm email is a field
var header = Object.keys(results.data[0]).map(i => i.toLowerCase() );
if (header.indexOf("email") == -1)
{
var bracketedHeaders = Object.keys(results.data[0]).map(i => "[" i "]" );
alert("Your CSV doesn't contain an email column. Make sure the name of the column is 'email', lower case, without dashes or extra spaces.nnColumns found (check for spaces):n" bracketedHeaders.join("n"));
return;
}
// all good? set data
MMContacts.isDirty = true;
MMContacts.data = results.data;
MMContacts.render();
}
});
},
refreshGrid: function()
{
// make fields
var fields = Object.keys(MMContacts.data[0]).map(function(i) {
return { name: i, type: "text" };
});
// add row # field
fields.unshift({name: "#", type: "text", css: "row-col"});
var index = 1;
var clone = JSON.parse(JSON.stringify(MMContacts.data));
clone.map(function(i) {
i["#"] = index ;
return i;
});
// show grid
MMContacts.grid.jsGrid({
height: "250px",
width: "100%",
data: clone,
fields: fields
});
}
}
$(MMContacts.init);
Часть формы в html:
<form id="mm-form" method="post">
<h2>Contacts</h2>
<span>Populate your target contacts</span>
<div id="limit-notice">
A single mail merge campaign is limited to 200 contacts (<a href="https://vocus.io/mailmerge-limit" target="_blank">learn why</a>).
The contact list you are trying to upload includes <span id="limit-uploaded"></span> contacts.
Consider splitting your contacts into multiple campaigns on different days to avoid the Gmail-imposed daily limit.
</div>
<div id="premium-notice">
Your plan is limited to 20 contacts per campaign, and no more than three campaigns. Please upgrade to the Starter or Professional Plan. See Dashboard amp;> Billing.
</div>
<div id="uploader">
drop CSV here<br>
make sure it has an "email" column
</div>
<div id="grid" style="display: none;"></div>
<div id="stats"></div>
<input type="hidden" name="dirty" value="false">
<input type="hidden" name="data" value="">
</form>
Комментарии:
1. Пожалуйста, поделитесь HTML или лучшим URL. И html входных данных
2. @Sers Я обновил весь скрипт. Это из Vocus, сервиса для электронной почты. Я думаю, вам нужно установить его, чтобы увидеть код. Затем, если вы попытаетесь выполнить слияние почты, вы сможете увидеть страницу, которую я описываю
Ответ №1:
У меня была эта проблема ранее, и я смог отобразить ввод с помощью javascript-исполнителя WebDriver. Вот как я это сделал на Java, код python должен быть довольно похожим.
evaluateJavascript("document.getElementById('upload').style['opacity'] = 1");
upload(jobseeker.cv()).to(find(By.cssSelector("#upload")));
Комментарии:
1. Спасибо! Я переведу это и попробую!
2. Вот 2 входных элемента <тип ввода= «скрытое» имя = «грязное» значение = «false»> <тип ввода= «скрытое» имя =»data» значение =»»»> Нет элемента с идентификатором =upload… Попытался обновить ваш код с помощью browser.execute_script(«document.getElementsByTagName (‘input’).style[‘opacity’] = 1») и получил «Не удается установить для свойства ‘opacity’ значение undefined» (обратите внимание на «s», иначе я получил неизвестную функцию)
3. Вместо этого используйте
name
атрибут. Поскольку имя не уникально, вы получите список элементов обратно. Вот пример, в котором я беру первый:document.getElementsByName("dirty")[0].style["opacity"] = 1
4. Хорошо, это сработало без ошибок. Для свойства style не задано значение «непрозрачность: 1;». Итак, что это upload.to ? Я привык загружать с помощью send_keys(). И он по-прежнему говорит «элемент не взаимодействует» с помощью send_keys (path_to_file). Пробовал с обоими элементами ввода (data и dirty)
5. Я почти уверен, что у меня получилось. Это, конечно, не единственный или лучший способ сделать это, но, похоже, он работает. Поскольку я не понимал, что происходит с файлом, после его загрузки я выбрал MMContacts [‘data’] и установил его в правильном формате (словарь, где строка заголовка является ключом, а значения — строками). Затем мне пришлось установить для свойства IsDirty значение true, иначе оно не сработало бы. Наконец, MMContacts.init(), а затем MMToolbar.next().