Best Python code snippet using uiautomator
epubview.py
Source:epubview.py
1# Copyright 2009 One Laptop Per Child2# Author: Sayamindu Dasgupta <sayamindu@laptop.org>3# WebKit2 port Copyright (C) 2018 Lubomir Rintel <lkundrak@v3.sk>4#5# This program is free software; you can redistribute it and/or modify6# it under the terms of the GNU General Public License as published by7# the Free Software Foundation; either version 2 of the License, or8# (at your option) any later version.9#10# This program is distributed in the hope that it will be useful,11# but WITHOUT ANY WARRANTY; without even the implied warranty of12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the13# GNU General Public License for more details.14#15# You should have received a copy of the GNU General Public License16# along with this program; if not, write to the Free Software17# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA18import gi19gi.require_version('WebKit2', '4.0')20from gi.repository import Gtk21from gi.repository import GObject22from gi.repository import Gdk23from gi.repository import WebKit224from . import widgets25import logging26import os.path27import math28import shutil29from .jobs import _JobPaginator as _Paginator30LOADING_HTML = '''31<html style="height: 100%; margin: 0; padding: 0; width: 100%;">32 <body style="display: table; height: 100%; margin: 0; padding: 0; width: 100%;">33 <div style="display: table-cell; text-align: center; vertical-align: middle;">34 <h1>Loading...</h1>35 </div>36 </body>37</html>38'''39class _View(Gtk.HBox):40 __gproperties__ = {41 'scale': (GObject.TYPE_FLOAT, 'the zoom level',42 'the zoom level of the widget',43 0.5, 4.0, 1.0, GObject.PARAM_READWRITE),44 }45 __gsignals__ = {46 'page-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE,47 ([int, int])),48 'selection-changed': (GObject.SignalFlags.RUN_FIRST, GObject.TYPE_NONE,49 ([])),50 }51 def __init__(self):52 GObject.threads_init()53 Gtk.HBox.__init__(self)54 self.connect("destroy", self._destroy_cb)55 self._ready = False56 self._paginator = None57 self._loaded_page = -158 # self._old_scrollval = -159 self._loaded_filename = None60 self._pagecount = -161 self.__scroll_to_end = False62 self.__page_changed = False63 self._has_selection = False64 self._scrollval = 0.065 self.scale = 1.066 self._epub = None67 self._findjob = None68 self.__in_search = False69 self.__search_fwd = True70 self._filelist = None71 self._internal_link = None72 self._view = widgets._WebView()73 self._view.load_html(LOADING_HTML, '/')74 settings = self._view.get_settings()75 settings.props.default_font_family = 'DejaVu LGC Serif'76 settings.props.enable_plugins = False77 settings.props.default_charset = 'utf-8'78 self._view.connect('load-changed', self._view_load_changed_cb)79 self._view.connect('scrolled', self._view_scrolled_cb)80 self._view.connect('scrolled-top', self._view_scrolled_top_cb)81 self._view.connect('scrolled-bottom', self._view_scrolled_bottom_cb)82 self._view.connect('selection-changed', self._view_selection_changed_cb)83 find = self._view.get_find_controller()84 find.connect('failed-to-find-text', self._find_failed_cb)85 self._eventbox = Gtk.EventBox()86 self._eventbox.connect('scroll-event', self._eventbox_scroll_event_cb)87 self._eventbox.add_events(Gdk.EventMask.SCROLL_MASK)88 self._eventbox.add(self._view)89 self._scrollbar = Gtk.VScrollbar()90 self._scrollbar_change_value_cb_id = self._scrollbar.connect(91 'change-value', self._scrollbar_change_value_cb)92 hbox = Gtk.HBox()93 hbox.pack_start(self._eventbox, True, True, 0)94 hbox.pack_end(self._scrollbar, False, True, 0)95 self.pack_start(hbox, True, True, 0)96 self._view.set_can_default(True)97 self._view.set_can_focus(True)98 def map_cp(widget):99 widget.setup_touch()100 widget.disconnect(self._setup_handle)101 self._setup_handle = self._view.connect('map', map_cp)102 def set_document(self, epubdocumentinstance):103 '''104 Sets document (should be a Epub instance)105 '''106 self._epub = epubdocumentinstance107 GObject.idle_add(self._paginate)108 def do_get_property(self, property):109 if property.name == 'has-selection':110 return self._has_selection111 elif property.name == 'scale':112 return self.scale113 else:114 raise AttributeError('unknown property %s' % property.name)115 def do_set_property(self, property, value):116 if property.name == 'scale':117 self.__set_zoom(value)118 else:119 raise AttributeError('unknown property %s' % property.name)120 def get_has_selection(self):121 '''122 Returns True if any part of the content is selected123 '''124 return self._has_selection125 def get_zoom(self):126 '''127 Returns the current zoom level128 '''129 return self.get_property('scale') * 100.0130 def set_zoom(self, value):131 '''132 Sets the current zoom level133 '''134 scrollbar_pos = self.get_vertical_pos()135 self._view.set_zoom_level(value / 100.0)136 self.set_vertical_pos(scrollbar_pos)137 def _get_scale(self):138 '''139 Returns the current zoom level140 '''141 return self.get_property('scale')142 def _set_scale(self, value):143 '''144 Sets the current zoom level145 '''146 self.set_property('scale', value)147 def zoom_in(self):148 '''149 Zooms in (increases zoom level by 0.1)150 '''151 if self.can_zoom_in():152 scrollbar_pos = self.get_vertical_pos()153 self._set_scale(self._get_scale() + 0.1)154 self.set_vertical_pos(scrollbar_pos)155 return True156 else:157 return False158 def zoom_out(self):159 '''160 Zooms out (decreases zoom level by 0.1)161 '''162 if self.can_zoom_out():163 scrollbar_pos = self.get_vertical_pos()164 self._set_scale(self._get_scale() - 0.1)165 self.set_vertical_pos(scrollbar_pos)166 return True167 else:168 return False169 def get_vertical_pos(self):170 """171 Used to save the scrolled position and restore when needed172 """173 return self._scrollval174 def set_vertical_pos(self, position):175 """176 Used to save the scrolled position and restore when needed177 """178 self._view.scroll_to(position)179 def can_zoom_in(self):180 '''181 Returns True if it is possible to zoom in further182 '''183 if self.scale < 4:184 return True185 else:186 return False187 def can_zoom_out(self):188 '''189 Returns True if it is possible to zoom out further190 '''191 if self.scale > 0.5:192 return True193 else:194 return False195 def get_current_page(self):196 '''197 Returns the currently loaded page198 '''199 return self._loaded_page200 def get_current_file(self):201 '''202 Returns the currently loaded XML file203 '''204 # return self._loaded_filename205 if self._paginator:206 return self._paginator.get_file_for_pageno(self._loaded_page)207 else:208 return None209 def get_pagecount(self):210 '''211 Returns the pagecount of the loaded file212 '''213 return self._pagecount214 def set_current_page(self, n):215 '''216 Loads page number n217 '''218 if n < 1 or n > self._pagecount:219 return False220 self._load_page(n)221 return True222 def next_page(self):223 '''224 Loads next page if possible225 Returns True if transition to next page is possible and done226 '''227 if self._loaded_page == self._pagecount:228 return False229 self._load_next_page()230 return True231 def previous_page(self):232 '''233 Loads previous page if possible234 Returns True if transition to previous page is possible and done235 '''236 if self._loaded_page == 1:237 return False238 self._load_prev_page()239 return True240 def scroll(self, scrolltype, horizontal):241 '''242 Scrolls through the pages.243 Scrolling is horizontal if horizontal is set to True244 Valid scrolltypes are:245 Gtk.ScrollType.PAGE_BACKWARD, Gtk.ScrollType.PAGE_FORWARD,246 Gtk.ScrollType.STEP_BACKWARD, Gtk.ScrollType.STEP_FORWARD247 Gtk.ScrollType.STEP_START and Gtk.ScrollType.STEP_END248 '''249 if scrolltype == Gtk.ScrollType.PAGE_BACKWARD:250 pages = self._paginator.get_pagecount_for_file(self._loaded_filename)251 self._view.scroll_by(self._page_height / pages * -1)252 elif scrolltype == Gtk.ScrollType.PAGE_FORWARD:253 pages = self._paginator.get_pagecount_for_file(self._loaded_filename)254 self._view.scroll_by(self._page_height / pages * 1)255 elif scrolltype == Gtk.ScrollType.STEP_BACKWARD:256 self._view.scroll_by(self._view.get_settings().get_default_font_size() * -3)257 elif scrolltype == Gtk.ScrollType.STEP_FORWARD:258 self._view.scroll_by(self._view.get_settings().get_default_font_size() * 3)259 elif scrolltype == Gtk.ScrollType.START:260 self.set_current_page(0)261 elif scrolltype == Gtk.ScrollType.END:262 self.__scroll_to_end = True263 self.set_current_page(self._pagecount - 1)264 else:265 print('Got unsupported scrolltype %s' % str(scrolltype))266 def __touch_page_changed_cb(self, widget, forward):267 if forward:268 self.scroll(Gtk.ScrollType.PAGE_FORWARD, False)269 else:270 self.scroll(Gtk.ScrollType.PAGE_BACKWARD, False)271 def copy(self):272 '''273 Copies the current selection to clipboard.274 '''275 self._view.run_javascript('document.execCommand("copy")')276 def find_next(self):277 '''278 Highlights the next matching item for current search279 '''280 self._view.grab_focus()281 self.__search_fwd = True282 self._view.get_find_controller().search_next()283 def find_previous(self):284 '''285 Highlights the previous matching item for current search286 '''287 self._view.grab_focus()288 self.__search_fwd = False289 self._view.get_find_controller().search_previous()290 def _find_failed_cb(self, find_controller):291 try:292 if self.__search_fwd:293 path = os.path.join(self._epub.get_basedir(),294 self._findjob.get_next_file())295 else:296 path = os.path.join(self._epub.get_basedir(),297 self._findjob.get_prev_file())298 self.__in_search = True299 self._load_file(path)300 except IndexError:301 # No match anywhere, no other file to pick302 pass303 def _find_changed(self, job):304 self._view.grab_focus()305 self._findjob = job306 find = self._view.get_find_controller()307 find.search (self._findjob.get_search_text(),308 self._findjob.get_flags(),309 GObject.G_MAXUINT)310 def __set_zoom(self, value):311 self._view.set_zoom_level(value)312 self.scale = value313 def _view_scrolled_cb(self, view, scrollval):314 if self._loaded_page < 1:315 return316 self._scrollval = scrollval317 scroll_upper = self._page_height318 scroll_page_size = self._view.get_allocated_height()319 if scrollval > 0:320 try:321 scrollfactor = scrollval / (scroll_upper - scroll_page_size)322 except ZeroDivisionError:323 scrollfactor = 0324 else:325 scrollfactor = 0326 if not self._loaded_page == self._pagecount and \327 not self._paginator.get_file_for_pageno(self._loaded_page) != \328 self._paginator.get_file_for_pageno(self._loaded_page + 1):329 scrollfactor_next = \330 self._paginator.get_scrollfactor_pos_for_pageno(331 self._loaded_page + 1)332 if scrollfactor >= scrollfactor_next:333 self._on_page_changed(self._loaded_page, self._loaded_page + 1)334 return335 if self._loaded_page > 1 and \336 not self._paginator.get_file_for_pageno(self._loaded_page) != \337 self._paginator.get_file_for_pageno(self._loaded_page - 1):338 scrollfactor_cur = \339 self._paginator.get_scrollfactor_pos_for_pageno(340 self._loaded_page)341 if scrollfactor <= scrollfactor_cur:342 self._on_page_changed(self._loaded_page, self._loaded_page - 1)343 return344 def _view_scrolled_top_cb(self, view):345 if self._loaded_page > 1:346 self.__scroll_to_end = True347 self._load_prev_page()348 def _view_scrolled_bottom_cb(self, view):349 if self._loaded_page < self._pagecount:350 self._load_next_page()351 def _view_selection_changed_cb(self, view, has_selection):352 self._has_selection = has_selection353 self.emit('selection-changed')354 def _eventbox_scroll_event_cb(self, view, event):355 if event.direction == Gdk.ScrollDirection.DOWN:356 self.scroll(Gtk.ScrollType.STEP_FORWARD, False)357 elif event.direction == Gdk.ScrollDirection.UP:358 self.scroll(Gtk.ScrollType.STEP_BACKWARD, False)359 def _view_load_changed_cb(self, v, load_event):360 if load_event != WebKit2.LoadEvent.FINISHED:361 return True362 filename = self._view.props.uri.replace('file://', '')363 if os.path.exists(filename.replace('xhtml', 'xml')):364 # Hack for making javascript work365 filename = filename.replace('xhtml', 'xml')366 filename = filename.split('#')[0] # Get rid of anchors367 if self._loaded_page < 1 or filename is None:368 return False369 self._loaded_filename = filename370 remfactor = self._paginator.get_remfactor_for_file(filename)371 pages = self._paginator.get_pagecount_for_file(filename)372 extra = int(math.ceil(373 remfactor * self._view.get_page_height() / (pages - remfactor)))374 if extra > 0:375 self._view.add_bottom_padding(extra)376 self._page_height = self._view.get_page_height()377 if self.__in_search:378 self.__in_search = False379 find = self._view.get_find_controller()380 find.search (self._findjob.get_search_text(),381 self._findjob.get_flags(self.__search_fwd),382 GObject.G_MAXUINT)383 else:384 self._scroll_page()385 # process_file = True386 if self._internal_link is not None:387 self._view.go_to_link(self._internal_link)388 vertical_pos = \389 self._view.get_vertical_position_element(self._internal_link)390 # set the page number based in the vertical position391 initial_page = self._paginator.get_base_pageno_for_file(filename)392 self._loaded_page = initial_page + int(393 vertical_pos / self._paginator.get_single_page_height())394 # There are epub files, created with Calibre,395 # where the link in the index points to the end of the previos396 # file to the needed chapter.397 # if the link is at the bottom of the page, we open the next file398 one_page_height = self._paginator.get_single_page_height()399 self._internal_link = None400 if vertical_pos > self._page_height - one_page_height:401 logging.error('bottom page link, go to next file')402 next_file = self._paginator.get_next_filename(filename)403 if next_file is not None:404 logging.error('load next file %s', next_file)405 self.__in_search = False406 self.__scroll_to_end = False407 # process_file = False408 GObject.idle_add(self._load_file, next_file)409# if process_file:410# # prepare text to speech411# html_file = open(self._loaded_filename)412# soup = BeautifulSoup.BeautifulSoup(html_file)413# body = soup.find('body')414# tags = body.findAll(text=True)415# self._all_text = ''.join([tag for tag in tags])416# self._prepare_text_to_speech(self._all_text)417 def _prepare_text_to_speech(self, page_text):418 i = 0419 j = 0420 word_begin = 0421 word_end = 0422 ignore_chars = [' ', '\n', '\r', '_', '[', '{', ']', '}', '|',423 '<', '>', '*', '+', '/', '\\']424 ignore_set = set(ignore_chars)425 self.word_tuples = []426 len_page_text = len(page_text)427 while i < len_page_text:428 if page_text[i] not in ignore_set:429 word_begin = i430 j = i431 while j < len_page_text and page_text[j] not in ignore_set:432 j = j + 1433 word_end = j434 i = j435 word_tuple = (word_begin, word_end,436 page_text[word_begin: word_end])437 if word_tuple[2] != '\r':438 self.word_tuples.append(word_tuple)439 i = i + 1440 def _scroll_page(self):441 v_upper = self._page_height442 if self.__scroll_to_end:443 # We need to scroll to the last page444 scrollval = v_upper445 self.__scroll_to_end = False446 else:447 pageno = self._loaded_page448 scrollfactor = self._paginator.get_scrollfactor_pos_for_pageno(pageno)449 scrollval = math.ceil(v_upper * scrollfactor)450 self._view.scroll_to(scrollval)451 def _paginate(self):452 filelist = []453 for i in self._epub._navmap.get_flattoc():454 filelist.append(os.path.join(self._epub._tempdir, i))455 # init files info456 self._filelist = filelist457 self._paginator = _Paginator(filelist)458 self._paginator.connect('paginated', self._paginated_cb)459 def get_filelist(self):460 return self._filelist461 def get_tempdir(self):462 return self._epub._tempdir463 def _load_next_page(self):464 self._load_page(self._loaded_page + 1)465 def _load_prev_page(self):466 self._load_page(self._loaded_page - 1)467 def _on_page_changed(self, oldpage, pageno):468 if oldpage == pageno:469 return470 self.__page_changed = True471 self._loaded_page = pageno472 self._scrollbar.handler_block(self._scrollbar_change_value_cb_id)473 self._scrollbar.set_value(pageno)474 self._scrollbar.handler_unblock(self._scrollbar_change_value_cb_id)475 # the indexes in read activity are zero based476 self.emit('page-changed', (oldpage - 1), (pageno - 1))477 def _load_page(self, pageno):478 if pageno > self._pagecount or pageno < 1:479 # TODO: Cause an exception480 return481 if self._loaded_page == pageno:482 return483 oldpage = self._loaded_page484 filename = self._paginator.get_file_for_pageno(pageno)485 filename = filename.replace('file://', '')486 if filename != self._loaded_filename:487 self._loaded_filename = filename488 """489 TODO: disabled because javascript can't be executed490 with the velocity needed491 # Copy javascript to highligth text to speech492 destpath, destname = os.path.split(filename.replace('file://', ''))493 shutil.copy('./epubview/highlight_words.js', destpath)494 self._insert_js_reference(filename.replace('file://', ''),495 destpath)496 IMPORTANT: Find a way to do this without modify the files497 now text highlight is implemented and the epub file is saved498 """499 self._view.stop_loading()500 if filename.endswith('xml'):501 dest = filename.replace('xml', 'xhtml')502 if not os.path.exists(dest):503 os.symlink(filename, dest)504 self._view.load_uri('file://' + dest)505 else:506 self._view.load_uri('file://' + filename)507 else:508 self._loaded_page = pageno509 self._scroll_page()510 self._on_page_changed(oldpage, pageno)511 def _insert_js_reference(self, file_name, path):512 js_reference = '<script type="text/javascript" ' + \513 'src="./highlight_words.js"></script>'514 o = open(file_name + '.tmp', 'a')515 for line in open(file_name):516 line = line.replace('</head>', js_reference + '</head>')517 o.write(line + "\n")518 o.close()519 shutil.copy(file_name + '.tmp', file_name)520 def _load_file(self, path):521 self._internal_link = None522 if path.find('#') > -1:523 self._internal_link = path[path.find('#'):]524 path = path[:path.find('#')]525 for filepath in self._filelist:526 if filepath.endswith(path):527 self._view.load_uri('file://' + filepath)528 oldpage = self._loaded_page529 self._loaded_page = \530 self._paginator.get_base_pageno_for_file(filepath)531 self._scroll_page()532 self._on_page_changed(oldpage, self._loaded_page)533 break534 def _scrollbar_change_value_cb(self, range, scrolltype, value):535 if scrolltype == Gtk.ScrollType.STEP_FORWARD or \536 scrolltype == Gtk.ScrollType.STEP_BACKWARD:537 self.scroll(scrolltype, False)538 elif scrolltype == Gtk.ScrollType.JUMP or \539 scrolltype == Gtk.ScrollType.PAGE_FORWARD or \540 scrolltype == Gtk.ScrollType.PAGE_BACKWARD:541 if value > self._scrollbar.props.adjustment.props.upper:542 self._load_page(self._pagecount)543 else:544 self._load_page(int(value))545 else:546 print('Warning: unknown scrolltype %s with value %f' \547 % (str(scrolltype), value))548 # FIXME: This should not be needed here549 self._scrollbar.set_value(self._loaded_page)550 if self.__page_changed:551 self.__page_changed = False552 return False553 else:554 return True555 def _paginated_cb(self, object):556 self._ready = True557 self._pagecount = self._paginator.get_total_pagecount()558 self._scrollbar.set_range(1.0, self._pagecount)559 self._scrollbar.set_increments(1.0, 1.0)560 self._view.grab_focus()561 self._view.grab_default()562 def _destroy_cb(self, widget):...
scraper.py
Source:scraper.py
...20 image_urls = set()21 image_count = 022 results_start = 023 while image_count < max_urls:24 self.__scroll_to_end(sleep_between_interactions)25 thumbnail_results = self.driver.find_elements_by_css_selector(26 "img.Q4LuWd")27 number_results = len(thumbnail_results)28 self.logger.info(29 f"Found: {number_results} search results. Extracting links from {results_start}:{number_results}")30 for img in thumbnail_results[results_start:number_results]:31 self.__click_and_wait(img, sleep_between_interactions)32 self.__add_image_urls_to_set(image_urls)33 image_count = len(image_urls)34 if image_count >= max_urls:35 self.logger.info(36 f"Found: {len(image_urls)} image links, done!")37 break38 else:39 self.logger.info(40 f"Found: {len(image_urls)} image links, looking for more ...")41 load_more_button = self.driver.find_element_by_css_selector(42 ".mye4qd")43 if load_more_button:44 self.logger.info("loading more...")45 self.driver.execute_script(46 "document.querySelector('.mye4qd').click();")47 # move the result startpoint further down48 results_start = len(thumbnail_results)49 return image_urls50 def persist_image(self, folder_path: str, url: str):51 """The persist_image function grabs an image URL url and downloads it into the folder_path. The function will assign the image a random 10-digit id."""52 image_content = self.__download_image_content(url)53 try:54 image_file = io.BytesIO(image_content)55 image = Image.open(image_file).convert('RGB')56 file_path = os.path.join(folder_path, hashlib.sha1(57 image_content).hexdigest()[:10] + '.jpg')58 with open(file_path, 'wb') as f:59 image.save(f, "JPEG", quality=85)60 self.logger.info(f"SUCCESS - saved {url} - as {file_path}")61 except Exception as e:62 self.logger.error(f"ERROR - Could not save {url} - {e}")63 def get_in_memory_image(self, url: str, format: str):64 image_content = self.__download_image_content(url)65 image_hash = hashlib.sha1(image_content).hexdigest()[:10] + '.jpeg'66 try:67 image_file = io.BytesIO(image_content)68 pil_image = Image.open(image_file).convert('RGB')69 in_mem_file = io.BytesIO()70 pil_image.save(in_mem_file, format=format)71 return in_mem_file.getvalue(), image_hash72 except Exception as e:73 self.logger.error(f"Could not get image data: {e}")74 def close_connection(self):75 self.driver.quit()76 def __download_image_content(self, url):77 try:78 return requests.get(url).content79 except Exception as e:80 self.logger.error(f"ERROR - Could not download {url} - {e}")81 def __scroll_to_end(self, sleep_time):82 self.driver.execute_script(83 "window.scrollTo(0, document.body.scrollHeight);")84 time.sleep(sleep_time)85 def __click_and_wait(self, img, wait_time):86 try:87 img.click()88 time.sleep(wait_time)89 except Exception:90 return91 def __add_image_urls_to_set(self, image_urls: set):92 actual_images = self.driver.find_elements_by_css_selector('img.n3VNCb')93 for actual_image in actual_images:94 if actual_image.get_attribute('src') and 'http' in actual_image.get_attribute('src'):95 image_urls.add(actual_image.get_attribute('src'))...
image_scraper.py
Source:image_scraper.py
...18 image_urls = set()19 image_count = 020 results_start = 021 while image_count < max_urls:22 self.__scroll_to_end(sleep_between_interactions)23 thumbnail_results = self.driver.find_elements_by_css_selector("img.Q4LuWd")24 number_results = len(thumbnail_results)25 self.logger.info(f"Found: {number_results} search results. Extracting links from {results_start}:{number_results}")26 for img in thumbnail_results[results_start:number_results]:27 self.__click_and_wait(img, sleep_between_interactions)28 self.__add_image_urls_to_set(image_urls)29 image_count = len(image_urls)30 if image_count >= max_urls:31 self.logger.info(f"Found: {len(image_urls)} image links, done!")32 break33 else:34 self.logger.info(f"Found: {len(image_urls)} image links, looking for more ...")35 load_more_button = self.driver.find_element_by_css_selector(".mye4qd")36 if load_more_button:37 self.logger.info("loading more...")38 self.driver.execute_script("document.querySelector('.mye4qd').click();")39 # move the result startpoint further down40 results_start = len(thumbnail_results)41 return image_urls42 def persist_image(self, folder_path: str, url: str):43 image_content = self.__download_image_content(url)44 try:45 image_file = io.BytesIO(image_content)46 image = Image.open(image_file).convert('RGB')47 file_path = os.path.join(folder_path, hashlib.sha1(image_content).hexdigest()[:10] + '.jpg')48 with open(file_path, 'wb') as f:49 image.save(f, "JPEG", quality=85)50 self.logger.info(f"SUCCESS - saved {url} - as {file_path}")51 except Exception as e:52 self.logger.error(f"ERROR - Could not save {url} - {e}")53 def get_in_memory_image(self, url: str, format: str):54 image_content = self.__download_image_content(url)55 try:56 image_file = io.BytesIO(image_content)57 pil_image = Image.open(image_file).convert('RGB')58 in_mem_file = io.BytesIO()59 pil_image.save(in_mem_file, format=format)60 return in_mem_file.getvalue()61 except Exception as e:62 self.logger.error(f"Could not get image data: {e}")63 def close_connection(self):64 self.driver.quit()65 def __download_image_content(self, url):66 try:67 return requests.get(url).content68 except Exception as e:69 self.logger.error(f"ERROR - Could not download {url} - {e}")70 def __scroll_to_end(self, sleep_time):71 self.driver.execute_script("window.scrollTo(0, document.body.scrollHeight);")72 time.sleep(sleep_time)73 def __click_and_wait(self, img, wait_time):74 try:75 img.click()76 time.sleep(wait_time)77 except Exception:78 return79 def __add_image_urls_to_set(self, image_urls: set):80 actual_images = self.driver.find_elements_by_css_selector('img.n3VNCb')81 for actual_image in actual_images:82 if actual_image.get_attribute('src') and 'http' in actual_image.get_attribute('src'):...
Learn to execute automation testing from scratch with LambdaTest Learning Hub. Right from setting up the prerequisites to run your first automation test, to following best practices and diving deeper into advanced test scenarios. LambdaTest Learning Hubs compile a list of step-by-step guides to help you be proficient with different test automation frameworks i.e. Selenium, Cypress, TestNG etc.
You could also refer to video tutorials over LambdaTest YouTube channel to get step by step demonstration from industry experts.
Get 100 minutes of automation test minutes FREE!!