Я написал класс на С#, который открывает веб-сайт и переводит введенный текст. Этот класс использует селен, который я использую для всего проекта.
Я не использую API, потому что с помощью веб-сайта я могу бесплатно переводить все символы, а с помощью API я должен за это платить. Это небольшой бизнес, так что...
В чем проблема: большую часть времени этот класс работает отлично, однако, когда вы устанавливаете длинную строку в качестве входных данных, я получаю сообщение об ошибке OpenQA.Selenium.WebDriverException: 'target frame detached (Session info: chrome=102.0.5005.63). Это также происходит, когда интернет-соединение недостаточно стабильно (например, обычный Wi-Fi). Не могу понять, как запрограммировать, чтобы программа ждала перевода. Кто-нибудь решение?
Основной код
public MainWindow()
{
InitializeComponent();
String[] franseZinnen = { "S’il vous plaît", "Je suis désolé", "Madame/Monsieur/Mademoiselle", "Excusez-moi", "Je ne comprends pas", "Je voudrais...", "Non, pas du tout", "Où sommes-nous?", "Pourriez-vous m’aider?", "Répétez s'il vous plaît.", "Où puis-je trouver un bon restaurant/café/la plage/le centre-ville?", "Je cherche cette adresse.", "J'ai besoin d'une chambre double..", "Je voudrais annuler ma réservation.", "Où est la boutique duty-free?", "Comment puis-je vous aider?", "Je cherche des chaussures.", "C’est combien?", "C’est trop cher!" };
List<String> uitkomsten = new List<string>();
String LangefranseTekst = "Temps ouais merde bière parce que du apéro. Vin vin croissant quelque manger. Quand même passer saucisson meilleur dans fromage quelque parce que.\r\nÀ la camembert boulangerie part omelette meilleur. Grève camembert fromage. Manger fois du coup carrément.\r\nEnée est juste le moyen de décorer l'oreiller de la vie. Duis eu tincidunt orci, de CNN. Tous mes besoins sont grands. Jusqu'à ce qu'il reçoive la messe et que l'urne flatte le laoreet. Proin reçoit beaucoup de rires. Suspendisse feugiat eros id risus vehicula lobortis. Vivamus ullamcorper orci a ligula pulvinar convallis.\r\nManger. Carrément guillotine saucisson épicé un apéro. Croissant boulangerie son du coup du coup moins quand même et paf le chien mais évidemment à révolution. À la du faire voila du coup. Évidemment entre et aussi voila.\r\nBaguette devoir camembert voila se disruptif disruptif et paf le chien se fais chier. Frenchtech se révolution monsieur du coup avec putain. Falloir disruptif grève comme même.\r\nVin omelette épicé. Comme même tout comme même. Peu camembert fromage parce que comme même voir ouais.\r\nDemander vin et aussi saucisson nous putain. De merde voila carrément et paf le chien il y a du coup aussi apéro.\r\nLe client est très important merci, le client sera suivi par le client. Énée n'a pas de justice, pas de résultat, pas de ligula, et la vallée veut la sauce. Morbi mais qui veut vendre une couche de contenu triste d'internet. Être ivre maintenant, mais ne pas être ivre maintenant, mon urne est d'une grande beauté, mais elle n'est pas aussi bien faite que dans un livre. Mécène dans la vallée de l'orc, dans l'élément même. Certaines des exigences faciles du budget, qu'il soit beaucoup de temps pour dignissim et. Je ne m'en fais pas chez moi, ça va être moche dans le vestibule. Mais aussi des protéines de Pour avant la fin de la semaine, qui connaît le poison, le résultat.";
/* // short translations
foreach (var item in franseZinnen)
{
ChromeDriver driver = new ChromeDriver();
String translation = vertalenNu.translateText(new ChromeDriver(), item, "fr", "en");
uitkomsten.Add(translation);
driver.Close();
}*/
// long translation
ChromeDriver driver = new ChromeDriver();
String translation = vertalenNu.translateText(new ChromeDriver(), LangefranseTekst, "fr", "en");
uitkomsten.Add(translation);
driver.Close();
String stringVoorBreakpoint = "";
}
Код в классе
[Serializable]
public class vertalenNu
{
public static String translateText(IWebDriver driver, String text, String languageSource, String languageDestination)
{
// nl - en - de - fr -es -it
driver.Url = "https://www.vertalen.nu/zinnen/";
driver.FindElement(By.Id("vertaaltxt")).SendKeys(text);
SelectElement testt = new SelectElement(driver.FindElement(By.Id("tselectfrom")));
testt.SelectByValue(languageSource);
SelectElement test = new SelectElement(driver.FindElement(By.Id("tselectto")));
test.SelectByValue(languageDestination);
driver.FindElement(By.XPath("//input[@title='Vertaal']")).Click();
WebDriverWait wait = new WebDriverWait(driver, TimeSpan.FromSeconds(20));
wait.Until(driver => driver.FindElement(By.ClassName("mt-translation-content")).Text != "");
IWebElement technicalSheet = driver.FindElement(By.ClassName("mt-translation-content"));
String technicalSheettext = technicalSheet.Text;
driver.Close();
driver.Quit();
return technicalSheettext;
}
}
Я ценю предложения, и я изменил их. однако основная проблема, к сожалению, остается. Любое решение для этого?
Это исключение означает, что вы закрыли вкладку/окно, в котором в данный момент находится драйвер. (так что это в номансленде) Хотя для этого есть и другие причины, я бы внимательно посмотрел, сколько Chromedrivers и браузеров вы запускаете. (Должен быть только один...) И убедитесь, что у вас нет осиротевших процессов после .Quit(). (Проверьте диспетчер задач) Используйте одну ссылку на драйвер повсюду и используйте .Quit() только после того, как закончите.
Кроме того, если вы создаете новый драйвер вскоре после закрытия одного из них, лучше включить сон между выходом из одного драйвера и созданием нового. Это даст драйверу/браузеру время на очистку. (временные папки и т. д.) Это поможет предотвратить бесхозные процессы драйвера. Вы также должны рассмотреть что-то более легкое, например драйвер HTMLUnit.
Вы можете попробовать это решение:
Сначала создайте класс, который будет обрабатывать переводы
public interface ITranslator : IDisposable
{
void ClearInput();
string Translate(string text);
}
public class Translator : ITranslator
{
private const string Url = "https://www.vertalen.nu/zinnen/";
private const int Timeout = 20;
private By _source = By.Id("vertaaltxt");
private By _destination = By.Id("resulttxt");
private By _submit = By.XPath("//input[@type = 'submit']");
private readonly WebDriverWait _wait;
private readonly IWebDriver _driver;
public Translator()
{
_driver = new ChromeDriver();
_wait = new WebDriverWait(_driver, TimeSpan.FromSeconds(Timeout));
_driver.Navigate().GoToUrl(Url);
}
public string Translate(string text)
{
_driver.FindElement(_source).SendKeys(text);
_driver.FindElement(_submit).Click();
_ = _wait.Until(d => d.FindElement(_destination).Text.Length > 0);
return _driver.FindElement(_destination).Text;
}
public void ClearInput()
{
_wait.Until(d => d.FindElement(_source)).Clear();
}
public void Dispose()
{
_driver.Dispose();
}
}
В следующем примере основное внимание уделяется решению WinForms, но вы можете настроить его для любого приложения с пользовательским интерфейсом, которое вам нравится:
public partial class MainWindow : Form
{
private readonly ITranslator _translator;
private const int MaxChars = 1500;
private int _currentCharsCount;
public MainWindow()
{
InitializeComponent();
_translator = new Translator();
}
private void translateBtn_Click(object sender, EventArgs e)
{
destinationTextBox.Text = _translator.Translate(sourceTextBox.Text);
_translator.ClearInput();
// or for better user experience use bellow code
// if you decide to use this code don't forget to mark async this method
//await Task.Run(() =>
//{
// destinationTextBox.Text = _translator.Translate(sourceTextBox.Text);
// _translator.ClearInput();
//});
}
private void MainWindow_FormClosing(object sender, FormClosingEventArgs e)
{
_translator.Dispose();
}
private void clickBtn_Click(object sender, EventArgs e)
{
sourceTextBox.Clear();
destinationTextBox.Clear();
charsCounter.Text = $"{MaxChars} characters remaining";
}
private void sourceTextBox_TextChanged(object sender, EventArgs e)
{
_currentCharsCount = MaxChars - sourceTextBox.TextLength;
charsCounter.Text = $"{_currentCharsCount} characters remaining";
}
}
Только что протестировал его с несколькими длинными текстовыми строками, и пока он работает отлично! Большое спасибо!
Я обновил код, чтобы интерфейс не зависал
Мне кажется, вы получаете драйверы-сироты... почему бы просто не сделать это?: vertalenNu.translateText(driver, ... Вместо того, чтобы создавать два драйвера? Вы также должны использовать только .quit(). Не используйте close (), если у вас нет нескольких окон/вкладок и вы пытаетесь закрыть одну из них. Удалите вызовы driver.Close() и driver.Quit() в функции. Вызовите driver.quit(), когда закончите работу с Водитель.