সেলেনিয়াম একটি বিদ্যমান ব্রাউজার সেশনের সাথে ইন্টারেক্ট করতে পারে?


103

সেলেনিয়াম (পছন্দসইভাবে ওয়েবড্রাইভার) সেলেনিয়াম ক্লায়েন্ট চালু করার আগে ইতিমধ্যে চলছে এমন একটি ব্রাউজারের সাথে যোগাযোগ করতে এবং অভিনয় করতে সক্ষম কিনা তা কি কেউ জানেন?

আমার অর্থ সেলেনিয়াম যদি সেলেনিয়াম সার্ভারটি ব্যবহার না করেই কোনও ব্রাউজারের সাথে যোগাযোগ করতে সক্ষম হয় (উদাহরণস্বরূপ কোনও ইন্টারনেট এক্সপ্লোরার নিজেই চালু করা যেতে পারে)।

উত্তর:


35

এটি বেশ পুরানো বৈশিষ্ট্যের অনুরোধ: ওয়েবড্রাইভারকে একটি চলমান ব্রাউজারে সংযুক্ত করার অনুমতি দিন । সুতরাং এটি আনুষ্ঠানিকভাবে সমর্থিত নয়।

যাইহোক, কিছু কার্যকরী কোড রয়েছে যা এটি সমর্থন করে বলে দাবি করে: https://web.archive.org/web/20171214043703/http://tarunlalवाणी . com / post / reusing-existing-browser-session-selenium-java/


আপনাকে অনেক ধন্যবাদ কারণ সেই লিঙ্কটিতে আমি একটি ক্লাস পেয়েছি যা এটি করতে দেয় তবে দুর্ভাগ্যক্রমে আমি এই সমাধানটি আইইয়ের সাথে ব্যবহার করতে পারি না (কেবল ফায়ারফক্সের সাথে)। আমি একটি নিয়মিত আইইডিগ্রাইভার চালু করতে যাচ্ছি এবং মিডলওয়্যার ব্যবহার করে এটি অন্য প্রকল্পগুলি থেকে এটির সাথে যোগাযোগ করব। আপনার যদি ধারণা থাকে যে ক্লাস কেন IE এ কাজ করছে না আমি এটির প্রশংসা করব। ধন্যবাদ.
অ্যাঞ্জেল রোমেরো

রবার্ট, এখন এর 2018। আপনি দয়া করে আপনার উত্তর আপডেট করতে পারেন?
মাস্টারজয়ে

যদি কারও এটির প্রয়োজন হয় তবে সেলেনিয়ামটি বিদ্যমান ব্রাউজার সেশনটি ব্যবহার করার জন্য আমি কয়েকটি জাভা কোডটি পরীক্ষা করে দেখেছি - stackoverflow.com/a/51145789/6648326
মাস্টারজয়ে

54

এটি একটি সদৃশ উত্তর ** পাইথন সেলেনিয়ামে একটি ড্রাইভারের সাথে সংযোগ স্থাপন করুন ** এটি সমস্ত ড্রাইভার এবং জাভা এপিআইয়ের জন্য প্রযোজ্য।

  1. একটি ড্রাইভার খুলুন
driver = webdriver.Firefox()  #python
  1. ড্রাইভার অবজেক্ট থেকে সেশন_ইড এবং _url এ বের করুন।
url = driver.command_executor._url       #"http://127.0.0.1:60622/hub"
session_id = driver.session_id            #'4e167f26-dc1d-4f51-a207-f761eaf73c31'
  1. আপনার ড্রাইভারের সাথে সংযোগ করতে এই দুটি প্যারামিটার ব্যবহার করুন।
driver = webdriver.Remote(command_executor=url,desired_capabilities={})
driver.close()   # this prevents the dummy browser
driver.session_id = session_id

এবং আপনি আবার আপনার ড্রাইভারের সাথে সংযুক্ত আছেন।

driver.get("http://www.mrsmart.in")

4
আমি ঠিক এটিই খুঁজছিলাম। ধন্যবাদ
মিলসো

6
এটি প্রতিলিপি ডামি ব্রাউজার প্রতিটি সময় উত্থাপন ছাড়া আমার জন্য কাজ করে।
পাভেল ভ্লাসভ

আমি ডামি উইন্ডোটিও পাচ্ছি, এটি কোনও চুক্তির মতো বড় নয়, তবে ডিবাগিংয়ের সময় এটি বিরক্তিকর। কীভাবে মুক্তি পাওয়ার জন্য কোনও ধারণা?
স্টিভ গন

4
+1 দ্বি-ফ্যাক্টর প্রমাণীকরণ লগইনগুলি এড়াতে আমার উদ্দেশ্যে কাজ করে তবে ডুপ্লিকেট ডামি ব্রাউজারগুলি উপস্থিত থাকে। আমি এটার সাথে বাঁচতে পারি।
স্যাম

4
selenium.common.exceptions.SessionNotCreatedException: Message: Session is already started
সেরিন

23

এই স্নিপেটটি সফলভাবে বিদ্যমান ব্রাউজারের দৃষ্টান্তটিকে পুনরায় ব্যবহার করার অনুমতি দেয় তবে ডুপ্লিকেট ব্রাউজারটি বাড়ানো এড়ানো যায়। তরুন লালওয়ানির ব্লগে পাওয়া গেছে ।

from selenium import webdriver
from selenium.webdriver.remote.webdriver import WebDriver

# executor_url = driver.command_executor._url
# session_id = driver.session_id

def attach_to_session(executor_url, session_id):
    original_execute = WebDriver.execute
    def new_command_execute(self, command, params=None):
        if command == "newSession":
            # Mock the response
            return {'success': 0, 'value': None, 'sessionId': session_id}
        else:
            return original_execute(self, command, params)
    # Patch the function before creating the driver object
    WebDriver.execute = new_command_execute
    driver = webdriver.Remote(command_executor=executor_url, desired_capabilities={})
    driver.session_id = session_id
    # Replace the patched function with original function
    WebDriver.execute = original_execute
    return driver

bro = attach_to_session('http://127.0.0.1:64092', '8de24f3bfbec01ba0d82a7946df1d1c3')
bro.get('http://ya.ru/')

4
অটোমেশনের মাধ্যমে বিদ্যমান সেশন আইডি এবং এক্সিকিউটারের URL খুঁজে পাওয়ার কোনও উপায় আছে কি? আমার ক্ষেত্রে, অন্য একটি অ্যাপ্লিকেশন একটি ব্রাউজার সেশন খোলায় এবং আমি এটি ব্যবহার করতে চাই। আপনি দয়া করে সুপারিশ করতে পারেন, কীভাবে এর ব্রাউজার সেশন আইডিটি সন্ধান করবেন?
সূর্যের সাইন

সম্ভবত আপনি স্ক্রিপ্ট শুরু হওয়ার সাথে সাথে এক্সিকিউটার_কম্যান্ড url এবং সেশন আইডি কোনও ফাইলের মধ্যে ফেলে দিতে পারেন এবং যখন আপনি আবার ব্রাউজার সেশনটি হুক করতে চান তখন ফাইলটি থেকে এটি পড়তে পারেন।
এস কে ভেঙ্কট

@ এসকেভেনক্যাট কীভাবে আমি ক্রোম উইন্ডোটির সেশন আইডি পেতে পারি, আমি পাইওয়িনোটো ব্যবহার করে এটি খুললাম এবং এখন এটিতে সেলেনুইম চালাতে চাই, ক্রোম ট্যাবের সেশন আইডি পাওয়ার কোনও অজগর উপায় আছে
তাইয়ব নাসির

@ তৈয়বনাছির, দয়া করে উপরের উত্তরটি দেখুন। যে পঞ্চম লাইনটি মন্তব্য করা হয়েছিল # session_id = driver.session_idতা হ'ল পাইথন সেলেনিয়াম এপি ব্যবহার করে আপনি ক্রোম উইন্ডোর সেশন আইডিটি পুনরুদ্ধার করতে পারেন। আমি অনুমান করি যে ক্রোম সেশনের প্রতিটি ট্যাবের অনন্য আইডি নেই।
এস কে ভেঙ্কট

4
@ এসকে আমি নিজেই খোলার ক্রোম উইন্ডোটির সেশন আইডি চাই, সেলেনিয়াম ব্যবহার করে আমি সেই উইন্ডোটি
খুলিনি

12

এটা সম্ভব. তবে আপনাকে এটিকে কিছুটা হ্যাক করতে হবে, একটি কোড রয়েছে যা যা করতে হবে তা হল একা দাঁড়িয়ে সার্ভার চালানো এবং "প্যাচ" রিমোটওয়েবড্রাইভার

public class CustomRemoteWebDriver : RemoteWebDriver
{
    public static bool newSession;
    public static string capPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestFiles", "tmp", "sessionCap");
    public static string sessiodIdPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "TestFiles", "tmp", "sessionid");

    public CustomRemoteWebDriver(Uri remoteAddress) 
        : base(remoteAddress, new DesiredCapabilities())
    {
    }

    protected override Response Execute(DriverCommand driverCommandToExecute, Dictionary<string, object> parameters)
    {
        if (driverCommandToExecute == DriverCommand.NewSession)
        {
            if (!newSession)
            {
                var capText = File.ReadAllText(capPath);
                var sidText = File.ReadAllText(sessiodIdPath);

                var cap = JsonConvert.DeserializeObject<Dictionary<string, object>>(capText);
                return new Response
                {
                    SessionId = sidText,
                    Value = cap
                };
            }
            else
            {
                var response = base.Execute(driverCommandToExecute, parameters);
                var dictionary = (Dictionary<string, object>) response.Value;
                File.WriteAllText(capPath, JsonConvert.SerializeObject(dictionary));
                File.WriteAllText(sessiodIdPath, response.SessionId);
                return response;
            }
        }
        else
        {
            var response = base.Execute(driverCommandToExecute, parameters);
            return response;
        }
    }
}

4
এই দুর্দান্ত সমাধানের ভিত্তিতে, আমি একটি সম্পূর্ণ ব্লগ পোস্ট লিখেছি যেখানে আমি ইতিমধ্যে খোলা ব্রাউজারের ক্রোমের সাথে কীভাবে সংযুক্ত হতে হবে তা নিয়ে আলোচনা করেছি। সম্পূর্ণ উত্স কোডটি সেই ব্লগ পোস্টে সংযুক্ত রয়েছে। binaryclips.com/2015/08/25/…

4

দেখা যাচ্ছে যে এই বৈশিষ্ট্যটি আনুষ্ঠানিকভাবে সেলেনিয়াম দ্বারা সমর্থিত নয়। তবে, তরুন লালওয়ানি ফিচারটি সরবরাহ করার জন্য ওয়ার্কিং জাভা কোড তৈরি করেছেন। উল্লেখ করুন - http: //tarunlalवाणी.com/ post/ reused- existing- browser- session- selenium- java/

উপরের লিঙ্কটি থেকে অনুলিপি করা এখানে কার্যকারী নমুনা কোড:

public static RemoteWebDriver createDriverFromSession(final SessionId sessionId, URL command_executor){
    CommandExecutor executor = new HttpCommandExecutor(command_executor) {

    @Override
    public Response execute(Command command) throws IOException {
        Response response = null;
        if (command.getName() == "newSession") {
            response = new Response();
            response.setSessionId(sessionId.toString());
            response.setStatus(0);
            response.setValue(Collections.<String, String>emptyMap());

            try {
                Field commandCodec = null;
                commandCodec = this.getClass().getSuperclass().getDeclaredField("commandCodec");
                commandCodec.setAccessible(true);
                commandCodec.set(this, new W3CHttpCommandCodec());

                Field responseCodec = null;
                responseCodec = this.getClass().getSuperclass().getDeclaredField("responseCodec");
                responseCodec.setAccessible(true);
                responseCodec.set(this, new W3CHttpResponseCodec());
            } catch (NoSuchFieldException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }

        } else {
            response = super.execute(command);
        }
        return response;
    }
    };

    return new RemoteWebDriver(executor, new DesiredCapabilities());
}

public static void main(String [] args) {

    ChromeDriver driver = new ChromeDriver();
    HttpCommandExecutor executor = (HttpCommandExecutor) driver.getCommandExecutor();
    URL url = executor.getAddressOfRemoteServer();
    SessionId session_id = driver.getSessionId();


    RemoteWebDriver driver2 = createDriverFromSession(session_id, url);
    driver2.get("http://tarunlalwani.com");
}

আপনার পরীক্ষার একটি বিদ্যমান ব্রাউজার সেশন থেকে একটি রিমোট ওয়েলড্রাইভার তৈরি করা দরকার। সেই ড্রাইভারটি তৈরি করতে আপনাকে কেবল "সেশন ইনফরমেশন", যেমন সার্ভারের ঠিকানা (আমাদের ক্ষেত্রে স্থানীয়) যেখানে ব্রাউজারটি চলছে এবং ব্রাউজার সেশন আইডিটি জানতে হবে। এই বিবরণগুলি পেতে, আমরা সেলেনিয়াম সহ একটি ব্রাউজার সেশন তৈরি করতে পারি, পছন্দসই পৃষ্ঠাটি খুলতে পারি এবং শেষ পর্যন্ত প্রকৃত পরীক্ষার স্ক্রিপ্টটি চালাতে পারি।

আমি জানি না যে কোনও সেশনের জন্য সেশন তথ্য পাওয়ার কোনও উপায় আছে যা সেলেনিয়াম দ্বারা তৈরি করা হয়নি।

এখানে সেশন তথ্যের উদাহরণ:

রিমোট সার্ভারের ঠিকানা: http: // লোকালহোস্ট: 24266 । প্রতিটি সেশনের জন্য পোর্ট নম্বর পৃথক। সেশন আইডি: 534c7b561aacdd6dc319f60fed27d9d6।


"সেলেনিয়াম দ্বারা তৈরি করা হয়নি এমন একটি অধিবেশনটির সেশন তথ্য পাওয়ার কোনও উপায় আছে কিনা আমি জানি না।" এটি আসলেই এমন একটি সমস্যা যা আমি ইতিমধ্যে কয়েক দিন ধরে চেষ্টা করেছিলাম ... এখনও কোনও সাফল্য নেই
সलेশ

@ স্লেশ - আমি আপনাকে এটির জন্য একটি নতুন প্রশ্ন তৈরি করার পরামর্শ দিচ্ছি এবং এটি যথেষ্ট মনোযোগ না পেলে আপনার 100 পয়েন্টের প্রস্তাব দিতে পারে।
মাস্টারজয়ে

তরুন লালওয়ানির কাজের উল্লেখের জন্য ধন্যবাদ। তার পৃষ্ঠা এবং আপনার উত্তরের মধ্যে, আমি এটি বের করতে সক্ষম হয়েছি। আমদানিগুলি দুর্দান্ত হত, পাশাপাশি কিছু বক্তব্যের উদ্দেশ্য ব্যাখ্যা করে মতামতও দিত। কিন্তু সব এবং সমস্ত, খুব সহায়ক।
তিহামার

4

এরিকের উত্তরে অনুপ্রাণিত হয়ে, সেলেনিয়াম ৩.7.০-এর জন্য আমার এই সমস্যার সমাধান এখানে। এ সমাধান সঙ্গে তুলনা http://tarunlalwani.com/post/reusing-existing-browser-session-selenium/ , সুবিধায় আছে একটি ফাঁকা ব্রাউজার উইন্ডোতে প্রতিটি সময় আমি বিদ্যমান অধিবেশন সংযোগ করতে হবে।

import warnings

from selenium.common.exceptions import WebDriverException
from selenium.webdriver.remote.errorhandler import ErrorHandler
from selenium.webdriver.remote.file_detector import LocalFileDetector
from selenium.webdriver.remote.mobile import Mobile
from selenium.webdriver.remote.remote_connection import RemoteConnection
from selenium.webdriver.remote.switch_to import SwitchTo
from selenium.webdriver.remote.webdriver import WebDriver


# This webdriver can directly attach to an existing session.
class AttachableWebDriver(WebDriver):
    def __init__(self, command_executor='http://127.0.0.1:4444/wd/hub',
                 desired_capabilities=None, browser_profile=None, proxy=None,
                 keep_alive=False, file_detector=None, session_id=None):
        """
        Create a new driver that will issue commands using the wire protocol.

        :Args:
         - command_executor - Either a string representing URL of the remote server or a custom
             remote_connection.RemoteConnection object. Defaults to 'http://127.0.0.1:4444/wd/hub'.
         - desired_capabilities - A dictionary of capabilities to request when
             starting the browser session. Required parameter.
         - browser_profile - A selenium.webdriver.firefox.firefox_profile.FirefoxProfile object.
             Only used if Firefox is requested. Optional.
         - proxy - A selenium.webdriver.common.proxy.Proxy object. The browser session will
             be started with given proxy settings, if possible. Optional.
         - keep_alive - Whether to configure remote_connection.RemoteConnection to use
             HTTP keep-alive. Defaults to False.
         - file_detector - Pass custom file detector object during instantiation. If None,
             then default LocalFileDetector() will be used.
        """
        if desired_capabilities is None:
            raise WebDriverException("Desired Capabilities can't be None")
        if not isinstance(desired_capabilities, dict):
            raise WebDriverException("Desired Capabilities must be a dictionary")
        if proxy is not None:
            warnings.warn("Please use FirefoxOptions to set proxy",
                          DeprecationWarning)
            proxy.add_to_capabilities(desired_capabilities)
        self.command_executor = command_executor
        if type(self.command_executor) is bytes or isinstance(self.command_executor, str):
            self.command_executor = RemoteConnection(command_executor, keep_alive=keep_alive)

        self.command_executor._commands['GET_SESSION'] = ('GET', '/session/$sessionId')  # added

        self._is_remote = True
        self.session_id = session_id  # added
        self.capabilities = {}
        self.error_handler = ErrorHandler()
        self.start_client()
        if browser_profile is not None:
            warnings.warn("Please use FirefoxOptions to set browser profile",
                          DeprecationWarning)

        if session_id:
            self.connect_to_session(desired_capabilities)  # added
        else:
            self.start_session(desired_capabilities, browser_profile)

        self._switch_to = SwitchTo(self)
        self._mobile = Mobile(self)
        self.file_detector = file_detector or LocalFileDetector()

        self.w3c = True  # added hardcoded

    def connect_to_session(self, desired_capabilities):
        response = self.execute('GET_SESSION', {
            'desiredCapabilities': desired_capabilities,
            'sessionId': self.session_id,
        })
        # self.session_id = response['sessionId']
        self.capabilities = response['value']

এটি ব্যবহার করতে:

if use_existing_session:
    browser = AttachableWebDriver(command_executor=('http://%s:4444/wd/hub' % ip),
                                  desired_capabilities=(DesiredCapabilities.INTERNETEXPLORER),
                                  session_id=session_id)
    self.logger.info("Using existing browser with session id {}".format(session_id))
else:
    browser = AttachableWebDriver(command_executor=('http://%s:4444/wd/hub' % ip),
                                  desired_capabilities=(DesiredCapabilities.INTERNETEXPLORER))
    self.logger.info('New session_id  : {}'.format(browser.session_id))

3

এখনও অবধি সমস্ত সমাধানের মধ্যে কিছু কার্যকারিতা নেই। এখানে আমার সমাধান:

public class AttachedWebDriver extends RemoteWebDriver {

    public AttachedWebDriver(URL url, String sessionId) {
        super();
        setSessionId(sessionId);
        setCommandExecutor(new HttpCommandExecutor(url) {
            @Override
            public Response execute(Command command) throws IOException {
                if (command.getName() != "newSession") {
                    return super.execute(command);
                }
                return super.execute(new Command(getSessionId(), "getCapabilities"));
            }
        });
        startSession(new DesiredCapabilities());
    }
}

এটি কী কার্যকারিতা যুক্ত করে (অন্যরা অনুপস্থিত)?
জুলানব

4
অভ্যন্তরীণভাবে, কেবল স্টার্টসেশন (...) পদ্ধতিটি দক্ষতার অবজেক্টটিকে আরম্ভ করবে। টেকস্ক্রিনশট, এক্সিকিউটসস্ক্রিপ্ট এবং আরও অনেক কিছুর জন্য ক্ষমতাগুলির অবজেক্টটি প্রয়োজনীয়। তবে স্টার্টসেশনে যাওয়ার মাধ্যমে আপনাকে একটি নতুন সেশন তৈরি করতে হবে। এই ওভারলোডটি একটি নতুন অধিবেশন তৈরি এড়িয়ে যায় তবে ততক্ষণে ক্ষমতা অবজেক্টের সূচনা হয়।
ইয়ানির

বন্ধু, স্ট্রিংকে ==
নরিল টেম্পেস্ট

3

জাভাস্ক্রিপ্ট সমাধান:

আমি এই ফাংশনটি ব্যবহার করে বিদ্যমান ব্রাউজার সেশনে সফলভাবে সংযুক্ত হয়েছি

webdriver.WebDriver.attachToSession(executor, session_id);

ডকুমেন্টেশন এখানে পাওয়া যাবে


4
এটি 4.0.0 সংস্করণে নেই!
গুগামঙ্গা

1

অজগরটিতে আমি একটি সমাধান পেয়েছি, আমি প্যারিসটেন ব্রোজার ক্লাসের ভিত্তিতে ওয়েবড্রাইভার ক্লাসটি সংশোধন করেছি।

https://github.com/axelPalmerin/personal/commit/fabddb38a39f378aa113b0cb8d33391d5f91dca5

ওয়েবড্রাইভার মডিউলটি প্রতিস্থাপন করুন:

এজে। ব্যবহার করা:

from selenium.webdriver.common.desired_capabilities import DesiredCapabilities

runDriver = sys.argv[1]
sessionId = sys.argv[2]

def setBrowser():
    if eval(runDriver):
        webdriver = w.Remote(command_executor='http://localhost:4444/wd/hub',
                     desired_capabilities=DesiredCapabilities.CHROME,
                     )
    else:
        webdriver = w.Remote(command_executor='http://localhost:4444/wd/hub',
                             desired_capabilities=DesiredCapabilities.CHROME,
                             session_id=sessionId)

    url = webdriver.command_executor._url
    session_id = webdriver.session_id
    print url
    print session_id
    return webdriver

0

আমি রেলস + শসাবার + সেলেনিয়াম ওয়েবড্রাইভার + ফ্যান্টমজেএস ব্যবহার করছি এবং আমি সেলেনিয়াম ওয়েবড্রাইভারের একটি বানরের দ্বারা চালিত সংস্করণ ব্যবহার করছি যা ফ্যান্টমজেএস ব্রাউজারকে পরীক্ষার রানের মধ্যে খোলা রাখে। এই ব্লগ পোস্টটি দেখুন: http://blog.sharetribe.com/2014/04/07/faster-cucumber-startup-keep-phantomjs-browser-open-between-tests/

এই পোস্টে আমার উত্তরটিও দেখুন: আমি কোনও রুবি ফাইল থেকে ইতিমধ্যে খোলা ব্রাউজারে একটি আদেশ কীভাবে কার্যকর করব


-1

এটি জাভাস্ক্রিপ্ট selenium-webdriverক্লায়েন্ট ব্যবহার করে বেশ সহজ :

প্রথমে নিশ্চিত হয়ে নিন যে আপনার ওয়েবড্রাইভার সার্ভার চলছে। উদাহরণস্বরূপ, ChromeDriver ডাউনলোড করুন , তারপরে চালানchromedriver --port=9515

দ্বিতীয়ত : চালককে এভাবে তৈরি করুন :

var driver = new webdriver.Builder()
   .withCapabilities(webdriver.Capabilities.chrome())
   .usingServer('http://localhost:9515')  // <- this
   .build();

এখানে একটি সম্পূর্ণ উদাহরণ:

var ওয়েবড্রাইভার = প্রয়োজন ('সেলেনিয়াম-ওয়েবড্রাইভার');

var driver = new webdriver.Builder()
   .withCapabilities(webdriver.Capabilities.chrome())
   .usingServer('http://localhost:9515')
   .build();

driver.get('http://www.google.com');
driver.findElement(webdriver.By.name('q')).sendKeys('webdriver');
driver.findElement(webdriver.By.name('btnG')).click();
driver.getTitle().then(function(title) {
   console.log(title);
 });

driver.quit();

4
এটি বিদ্যমান ব্রাউজার সেশন ব্যবহার করে না। এটি একটি নতুন ক্রোমড্রাইভার সেশন তৈরি করে এবং একটি নতুন ব্রাউজার উইন্ডো খুলবে। এবং getAllWindowHandles () আপনার পুরানো ব্রাউজার উইন্ডোটির হ্যান্ডেলটি প্রদর্শন করবে না।
জেনারেল

আপডেট: রয়েছে সেলেনিয়ামএইচকি.ইথিটুব.ইও / সেলেনিয়াম / ডকস / অ্যাপি / জাভাস্ক্রিপ্ট / মডুল /… যা বিদ্যমান খোলা ব্রাউজার উইন্ডোতে সংযোগ করতে দেয়।
ডিজেলি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.