33
44from io import BytesIO
55from PIL import Image , ImageGrab
6- import os
76
87
9- async def take_screenshot (url :str , image_name :str = None , quality :int = 100 ):
8+ async def take_screenshot (url : str , save_path : str = None , quality : int = 100 ):
9+ """
10+ Takes a screenshot of a webpage at the specified URL and saves it if the save_path is specified.
11+ Parameters:
12+ url (str): The URL of the webpage to take a screenshot of.
13+ save_path (str): The path to save the screenshot to. Defaults to None.
14+ quality (int): The quality of the jpeg image, between 1 and 100. Defaults to 100.
15+ Returns:
16+ PIL.Image: The screenshot of the webpage as a PIL Image object.
17+ """
18+
1019 async with async_playwright () as p :
1120 browser = await p .chromium .launch (headless = True )
1221 page = await browser .new_page ()
1322 await page .goto (url )
14- save_path = None
15- if image_name is not None :
16- dir_path = os .path .abspath ('' )
17- save_path = dir_path + "/scrapegraphai/sreenshot_scraping/saved_screenshots/" + image_name
18- image_bytes = await page .screenshot (path = save_path ,type = "jpeg" ,full_page = True ,quality = quality )
23+ image_bytes = await page .screenshot (path = save_path , type = "jpeg" , full_page = True , quality = quality )
1924 await browser .close ()
2025 return Image .open (BytesIO (image_bytes ))
2126
2227
2328def select_area_with_opencv (image ):
29+ """
30+ Allows you to manually select an image area using OpenCV. It is recommended to use this function if your project is on your computer, otherwise use select_area_with_ipywidget().
31+ Parameters:
32+ image (PIL.Image): The image from which to select an area.
33+ Returns:
34+ A tuple containing the LEFT, TOP, RIGHT, and BOTTOM coordinates of the selected area.
35+ """
36+
2437 import cv2 as cv
2538 import numpy as np
2639
2740 fullscreen_screenshot = ImageGrab .grab ()
28- dw , dh = fullscreen_screenshot .size
41+ dw , dh = fullscreen_screenshot .size
2942
3043 def draw_selection_rectanlge (event , x , y , flags , param ):
31- global ix ,iy ,drawing ,overlay , img
44+ global ix , iy , drawing , overlay , img
3245 if event == cv .EVENT_LBUTTONDOWN :
3346 drawing = True
34- ix ,iy = x ,y
47+ ix , iy = x , y
3548 elif event == cv .EVENT_MOUSEMOVE :
3649 if drawing == True :
3750 cv .rectangle (img , (ix , iy ), (x , y ), (41 , 215 , 162 ), - 1 )
38- cv .putText (img , 'PRESS ANY KEY TO SELECT THIS AREA' , (ix , iy - 10 ), cv .FONT_HERSHEY_SIMPLEX , 1.5 , (55 ,46 ,252 ), 5 )
39- img = cv .addWeighted (overlay , alpha , img , 1 - alpha , 0 )
51+ cv .putText (img , 'PRESS ANY KEY TO SELECT THIS AREA' , (ix ,
52+ iy - 10 ), cv .FONT_HERSHEY_SIMPLEX , 1.5 , (55 , 46 , 252 ), 5 )
53+ img = cv .addWeighted (overlay , alpha , img , 1 - alpha , 0 )
4054 elif event == cv .EVENT_LBUTTONUP :
41- global LEFT ,TOP ,RIGHT ,BOTTOM
42-
55+ global LEFT , TOP , RIGHT , BOTTOM
56+
4357 drawing = False
44- if ix < x :
45- LEFT = int (ix )
46- RIGHT = int (x )
58+ if ix < x :
59+ LEFT = int (ix )
60+ RIGHT = int (x )
4761 else :
48- LEFT = int (x )
49- RIGHT = int (ix )
50- if iy < y :
51- TOP = int (iy )
52- BOTTOM = int (y )
62+ LEFT = int (x )
63+ RIGHT = int (ix )
64+ if iy < y :
65+ TOP = int (iy )
66+ BOTTOM = int (y )
5367 else :
54- TOP = int (y )
55- BOTTOM = int (iy )
68+ TOP = int (y )
69+ BOTTOM = int (iy )
5670
57- global drawing ,ix ,iy ,overlay ,img
71+ global drawing , ix , iy , overlay , img
5872 drawing = False
59- ix ,iy = - 1 ,- 1
73+ ix , iy = - 1 , - 1
6074
61- img = np .array (image )
75+ img = np .array (image )
6276 img = cv .cvtColor (img , cv .COLOR_RGB2BGR )
6377
64- img = cv .rectangle (img , (0 , 0 ), (image .size [0 ], image .size [1 ]), (0 ,0 ,255 ), 10 )
65- img = cv .putText (img , 'SELECT AN AREA' , (int (image .size [0 ]* 0.3 ), 100 ), cv .FONT_HERSHEY_SIMPLEX , 2 , (0 ,0 ,255 ), 5 )
66-
78+ img = cv .rectangle (
79+ img , (0 , 0 ), (image .size [0 ], image .size [1 ]), (0 , 0 , 255 ), 10 )
80+ img = cv .putText (img , 'SELECT AN AREA' , (int (
81+ image .size [0 ]* 0.3 ), 100 ), cv .FONT_HERSHEY_SIMPLEX , 2 , (0 , 0 , 255 ), 5 )
82+
6783 overlay = img .copy ()
6884 alpha = 0.3
6985
7086 while True :
71- cv .namedWindow ('SELECT AREA' , cv .WINDOW_KEEPRATIO )
87+ cv .namedWindow ('SELECT AREA' , cv .WINDOW_KEEPRATIO )
7288 cv .setMouseCallback ('SELECT AREA' , draw_selection_rectanlge )
73- cv .resizeWindow ('SELECT AREA' , int (image .size [0 ]/ (image .size [1 ]/ dh )), dh )
74-
75- cv .imshow ('SELECT AREA' ,img )
89+ cv .resizeWindow ('SELECT AREA' , int (
90+ image .size [0 ]/ (image .size [1 ]/ dh )), dh )
91+
92+ cv .imshow ('SELECT AREA' , img )
7693
7794 if cv .waitKey (20 ) > - 1 :
7895 break
79-
96+
8097 cv .destroyAllWindows ()
8198 return LEFT , TOP , RIGHT , BOTTOM
8299
100+
83101def select_area_with_ipywidget (image ):
102+ """
103+ Allows you to manually select an image area using ipywidgets. It is recommended to use this function if your project is in Google Colab, Kaggle or other similar platform, otherwise use select_area_with_opencv().
104+ Parameters:
105+ image (PIL Image): The input image.
106+ Returns:
107+ None
108+ """
109+
84110 import matplotlib .pyplot as plt
85111 import numpy as np
86112 from ipywidgets import interact , IntSlider
87113 import ipywidgets as widgets
88114 from PIL import Image
89115
90-
91- # Load an image
92- # image_path = 'piping-yes-when-running-scripts-from-curl.jpeg' # Replace with your image path
93- # image = Image.open(image_path)
94116 img_array = np .array (image )
95117
96118 print (img_array .shape )
97119
98- def update_plot (top_bottom ,left_right ,image_size ):
99- plt .figure (figsize = (image_size ,image_size ))
120+ def update_plot (top_bottom , left_right , image_size ):
121+ plt .figure (figsize = (image_size , image_size ))
100122 plt .imshow (img_array )
101123 plt .axvline (x = left_right [0 ], color = 'blue' , linewidth = 1 )
102- plt .text (left_right [0 ]+ 1 ,- 25 ,'LEFT' ,rotation = 90 ,color = 'blue' )
124+ plt .text (left_right [0 ]+ 1 , - 25 , 'LEFT' , rotation = 90 , color = 'blue' )
103125 plt .axvline (x = left_right [1 ], color = 'red' , linewidth = 1 )
104- plt .text (left_right [1 ]+ 1 ,- 25 ,'RIGHT' ,rotation = 90 , color = 'red' )
105-
106-
107- plt .axhline (y = img_array .shape [0 ]- top_bottom [0 ], color = 'green' , linewidth = 1 )
108- plt .text (- 100 ,img_array .shape [0 ]- top_bottom [0 ]+ 1 ,'BOTTOM' , color = 'green' )
109- plt .axhline (y = img_array .shape [0 ]- top_bottom [1 ], color = 'darkorange' , linewidth = 1 )
110- plt .text (- 100 ,img_array .shape [0 ]- top_bottom [1 ]+ 1 ,'TOP' , color = 'darkorange' )
111- plt .axis ('off' ) # Hide axes
126+ plt .text (left_right [1 ]+ 1 , - 25 , 'RIGHT' , rotation = 90 , color = 'red' )
127+
128+ plt .axhline (y = img_array .shape [0 ] -
129+ top_bottom [0 ], color = 'green' , linewidth = 1 )
130+ plt .text (- 100 , img_array .shape [0 ] -
131+ top_bottom [0 ]+ 1 , 'BOTTOM' , color = 'green' )
132+ plt .axhline (y = img_array .shape [0 ]- top_bottom [1 ],
133+ color = 'darkorange' , linewidth = 1 )
134+ plt .text (- 100 , img_array .shape [0 ] -
135+ top_bottom [1 ]+ 1 , 'TOP' , color = 'darkorange' )
136+ plt .axis ('off' )
112137 plt .show ()
113138
114-
115- top_bottom_slider = widgets .IntRangeSlider (
139+ top_bottom_slider = widgets .IntRangeSlider (
116140 value = [int (img_array .shape [0 ]* 0.25 ), int (img_array .shape [0 ]* 0.75 )],
117141 min = 0 ,
118142 max = img_array .shape [0 ],
@@ -125,7 +149,7 @@ def update_plot(top_bottom,left_right,image_size):
125149 readout_format = 'd' ,
126150 )
127151
128- left_right_slider = widgets .IntRangeSlider (
152+ left_right_slider = widgets .IntRangeSlider (
129153 value = [int (img_array .shape [1 ]* 0.25 ), int (img_array .shape [1 ]* 0.75 )],
130154 min = 0 ,
131155 max = img_array .shape [1 ],
@@ -137,7 +161,7 @@ def update_plot(top_bottom,left_right,image_size):
137161 readout = True ,
138162 readout_format = 'd' ,
139163 )
140- image_size_bt = widgets .BoundedIntText (
164+ image_size_bt = widgets .BoundedIntText (
141165 value = 10 ,
142166 min = 2 ,
143167 max = 20 ,
@@ -146,11 +170,44 @@ def update_plot(top_bottom,left_right,image_size):
146170 disabled = False
147171 )
148172
149- interact (update_plot ,top_bottom = top_bottom_slider ,left_right = left_right_slider ,image_size = image_size_bt )
173+ interact (update_plot , top_bottom = top_bottom_slider ,
174+ left_right = left_right_slider , image_size = image_size_bt )
175+
176+
177+ def crop_image (image , LEFT = None , TOP = None , RIGHT = None , BOTTOM = None , save_path : str = None ):
178+ """
179+ Crop an image using the specified coordinates.
180+ Parameters:
181+ image (PIL.Image): The image to be cropped.
182+ LEFT (int, optional): The x-coordinate of the left edge of the crop area. Defaults to None.
183+ TOP (int, optional): The y-coordinate of the top edge of the crop area. Defaults to None.
184+ RIGHT (int, optional): The x-coordinate of the right edge of the crop area. Defaults to None.
185+ BOTTOM (int, optional): The y-coordinate of the bottom edge of the crop area. Defaults to None.
186+ save_path (str, optional): The path to save the cropped image. Defaults to None.
187+ Returns:
188+ PIL.Image: The cropped image.
189+ Notes:
190+ If any of the coordinates (LEFT, TOP, RIGHT, BOTTOM) is None, it will be set to the corresponding edge of the image.
191+ If save_path is specified, the cropped image will be saved as a JPEG file at the specified path.
192+ """
193+
194+ if LEFT is None :
195+ LEFT = 0
196+ if TOP is None :
197+ TOP = 0
198+ if RIGHT is None :
199+ RIGHT = image .size [0 ]
200+ if BOTTOM is None :
201+ BOTTOM = image .size [1 ]
202+
203+ croped_image = image .crop ((LEFT , TOP , RIGHT , BOTTOM ))
204+ if save_path is not None :
205+ from pathlib import Path
206+ croped_image .save (save_path , "JPEG" )
150207
151- def crop_image (image ,TOP = None , BOTTOM = None , LEFT = None , RIGHT = None , save :bool = True ):
152208 return image .crop ((LEFT , TOP , RIGHT , BOTTOM ))
153209
154210
155- # image=asyncio.run(take_screenshot("https://unix.stackexchange.com/questions/690233/piping-yes-when-running-scripts-from-curl"))
211+
212+ # image=asyncio.run(take_screenshot("https://unix.stackexchange.com/questions/690233/piping-yes-when-running-scripts-from-curl", save_path="saved_screenshots/image.jpeg"))
156213# print(select_area_with_opencv(image))
0 commit comments