Skip to content
Open
Changes from 1 commit
Commits
Show all changes
26 commits
Select commit Hold shift + click to select a range
e155871
Review- Removing unused imports
Ihebdhouibi Sep 15, 2024
8e43594
Review- Adding windows timeout mechanism
Ihebdhouibi Sep 15, 2024
04bb477
Review- removing obselete code
Ihebdhouibi Sep 15, 2024
694330d
Review- Encapsulate global variable in a config class
Ihebdhouibi Sep 15, 2024
48a7ecf
Review- fixing typo in ScraperConfig class
Ihebdhouibi Sep 15, 2024
9d03605
Review- fixing typo in timeout cnstr
Ihebdhouibi Sep 15, 2024
31fdb56
Review- Fixing search_download call
Ihebdhouibi Sep 15, 2024
34e6cad
Review- missing parentheses
Ihebdhouibi Sep 15, 2024
173afd2
Review- fixing typo
Ihebdhouibi Sep 15, 2024
2c863d7
Review- search_download call fix
Ihebdhouibi Sep 15, 2024
d948deb
Review- Establishing DB connection using context manager
Ihebdhouibi Sep 15, 2024
704250c
Review- Removing commented lines
Ihebdhouibi Sep 15, 2024
b58e70d
Review- Apply code reusebility to store alerts functions
Ihebdhouibi Sep 15, 2024
f7e3782
Review- Apply code reusebility to retrieving alerts functions
Ihebdhouibi Sep 15, 2024
042b951
Review- Add exception handling
Ihebdhouibi Sep 15, 2024
6289aa9
Review- Add remove_camera function
Ihebdhouibi Sep 15, 2024
5a17c59
Review- Fixing typo
Ihebdhouibi Sep 15, 2024
d628218
Review- Add exception handling
Ihebdhouibi Sep 15, 2024
caebad0
Review- Fixing typo and naming in functions
Ihebdhouibi Sep 15, 2024
8517949
Review- Updating create_azure_container function
Ihebdhouibi Sep 15, 2024
4075fc5
Review- Remove commented lines
Ihebdhouibi Sep 15, 2024
f7893a4
Review- Updating upload_blob function
Ihebdhouibi Sep 15, 2024
244dcb2
Review- removing debbuging and unecessary lines
Ihebdhouibi Sep 15, 2024
aae9185
Review- Removing unecessary prints
Ihebdhouibi Sep 16, 2024
f1e5c12
Review- Removing commented code
Ihebdhouibi Sep 16, 2024
39616c3
Review- Documenting functions
Ihebdhouibi Sep 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
83 changes: 48 additions & 35 deletions ImagesScrapper.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import hashlib
import time
import io
import os
import requests
from bs4 import BeautifulSoup
Expand All @@ -11,28 +12,6 @@
import platform
import threading

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Using threading.timer to provide timeout mechanism for windows


driver_path = '/home/iheb/chromedriver'
output_path = 'data/images/robbery_images'
number_of_images = 1000
GET_IMAGE_TIMEOUT = 2
SLEEP_BETWEEN_INTERACTIONS = 0.1
SLEEP_BEFORE_MORE = 5
IMAGE_QUALITY = 1024
search_terms = ["armed robbery",
"shop robbery",
"man wearing robber mask",
"man wearing robber mask and knife",
"shop armed looting",

"persons",
"store customers",
"faces",
"covid mask",
"person portrait",
"full body person portrait",
"person smiling"]
# search_terms = ["armed masked thief"]

Comment thread
Ihebdhouibi marked this conversation as resolved.
Outdated

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

removing global variables will improve flexibility and maintainability

class TimeoutException(Exception):
pass

Expand Down Expand Up @@ -67,14 +46,49 @@ def __exit__(self, type, value, traceback):
def _raise_timeout(self):
raise TimeoutException(self.error_message)

class ScraperConfig:

def __init__(self, driver_path, output_path, number_of_images, get_image_timeout, sleep_between_interactions, slee_before_more
, image_quality, search_terms):
self.driver_path = driver_path
self.output_path = output_path
self.number_of_images = number_of_images
self.get_image_timeout = get_image_timeout
self.sleep_between_interactions = sleep_between_interactions
self.sleep_before_more = slee_before_more
self.image_quality = image_quality
self.search_terms = search_terms

config = ScraperConfig(
driver_path = '/home/iheb/chromedriver',
output_path = 'data/images/robbery_images',
number_of_images = 1000,
GET_IMAGE_TIMEOUT = 2,
SLEEP_BETWEEN_INTERACTIONS = 0.1,
SLEEP_BEFORE_MORE = 5,
IMAGE_QUALITY = 1024,
search_terms = ["armed robbery",
"shop robbery",
"man wearing robber mask",
"man wearing robber mask and knife",
"shop armed looting",
"persons",
"store customers",
"faces",
"covid mask",
"person portrait",
"full body person portrait",
"person smiling"]
)

def fetch_image_urls(query: str,
max_links_to_fetch: int,
wd: webdriver,
sleep_between_interactions: int = 1):
config: ScraperConfig):

def scroll_to_end(wd):
wd.execute_script("window.scrollTo(0, document.body.scrollHeight);")
time.sleep(sleep_between_interactions)
time.sleep(config.sleep_between_interactions)

# building google query
search_url = "https://www.google.com/search?safe=off&site=&tbm=isch&source=hp&q={q}&oq={q}&gs_l=img"
Expand All @@ -100,7 +114,7 @@ def scroll_to_end(wd):
# try to click every thumbnail such that we can get the real image behind it
try:
img.click()
time.sleep(sleep_between_interactions)
time.sleep(config.sleep_between_interactions)
except Exception as e:
print(f"could not click image - {e}")
continue
Expand Down Expand Up @@ -144,11 +158,11 @@ def scroll_to_end(wd):

return image_urls

def persist_image(folder_path:str, url:str):
def persist_image(folder_path:str,url:str, config: ScraperConfig):
try:
print("getting the image...")
# download the image, if timeout is exceeded throw an error
with timeout(GET_IMAGE_TIMEOUT):
with timeout(config.GET_IMAGE_TIMEOUT):
image_content = requests.get(url).content
except Exception as e:
print(f"Error - Could not download {url} - {e}")
Expand All @@ -159,14 +173,13 @@ def persist_image(folder_path:str, url:str):
file_path = os.path.join(folder_path, hashlib.sha1(image_content).hexdigest()[:10] + '.jpg')

with open(file_path, 'wb') as f:
image.save(f, "JPEG", quality=IMAGE_QUALITY)
image.save(f, "JPEG", quality=config.IMAGE_QUALITY)
print(f"Success - Saved {url} - as {file_path} ")

except Exception as e:
print(f"Error - could not save {url} - {e}")

def search_download(search_term:str, target_path="data/images/robbery_images", number_images=5):

def search_download(search_term:str, config: ScraperConfig, target_path="data/images/robbery_images", number_images=5):
# create a folder name
target_folder = os.path.join(target_path, '_'.join(search_term.lower().split(" ")))

Expand All @@ -175,8 +188,8 @@ def search_download(search_term:str, target_path="data/images/robbery_images", n
os.makedirs(target_folder)

# launch chrome
with webdriver.Chrome(executable_path=driver_path) as wd:
res = fetch_image_urls(search_term, number_images, wd= wd, sleep_between_interactions=SLEEP_BETWEEN_INTERACTIONS)
with webdriver.Chrome(executable_path=config.driver_path) as wd:
res = fetch_image_urls(search_term, number_images, wd= wd, sleep_between_interactions=config.SLEEP_BETWEEN_INTERACTIONS)

Copy link
Copy Markdown
Owner Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

after removing global variables we can directly use config instance attributes


# download images
if res is not None:
Expand All @@ -186,7 +199,7 @@ def search_download(search_term:str, target_path="data/images/robbery_images", n
print(f"failed to return links for terms : {search_term}")


for term in search_terms:
for term in config.search_terms:
search_download(term,
output_path,
number_of_images)
config.output_path,
config.number_of_images)