supli6669 commited on
Commit
1adbdeb
·
1 Parent(s): 83483d2

feat: add Pinterest crawling support, update dependencies and meta_info

Browse files
crawl_datasets.py CHANGED
@@ -5,6 +5,11 @@ import pandas as pd
5
  from PIL import Image
6
  import requests
7
  import time
 
 
 
 
 
8
 
9
  # ─────────────────────────────────────────────
10
  # HuggingFace dataset sources
@@ -31,6 +36,15 @@ SOURCES = {
31
  "prefix": "anime",
32
  "description": "Anime Face Dataset 10k illustrations",
33
  },
 
 
 
 
 
 
 
 
 
34
  }
35
 
36
  # Fallback: direct image download lists for anime / landscape
@@ -75,6 +89,89 @@ def extract_image_bytes(cell) -> bytes | None:
75
  return None
76
 
77
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
78
  def crawl_source(name: str, cfg: dict, base_dataset_dir: str):
79
  """Download images for a single source category."""
80
  save_dir = os.path.join(base_dataset_dir, cfg["subdir"])
@@ -86,6 +183,28 @@ def crawl_source(name: str, cfg: dict, base_dataset_dir: str):
86
  print(f" Target : {cfg['num_images']} images")
87
  print(f"{'='*55}")
88
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
89
  df = load_parquet_safe(cfg["parquet_url"])
90
 
91
  # Try fallbacks if primary failed
 
5
  from PIL import Image
6
  import requests
7
  import time
8
+ from bs4 import BeautifulSoup
9
+ # Selenium for dynamic page rendering (Pinterest loads images via JS)
10
+ from selenium import webdriver
11
+ from selenium.webdriver.chrome.options import Options
12
+ from webdriver_manager.chrome import ChromeDriverManager
13
 
14
  # ─────────────────────────────────────────────
15
  # HuggingFace dataset sources
 
36
  "prefix": "anime",
37
  "description": "Anime Face Dataset 10k illustrations",
38
  },
39
+ "blue_archive": {
40
+ # This source is a web‑scrape target rather than a parquet dataset.
41
+ "type": "web",
42
+ "search_url": "https://www.pinterest.com/search/pins/?q=blue%20archive",
43
+ "num_images": 300,
44
+ "subdir": "blue_archive",
45
+ "prefix": "blue",
46
+ "description": "Blue Archive images scraped from Pinterest",
47
+ },
48
  }
49
 
50
  # Fallback: direct image download lists for anime / landscape
 
89
  return None
90
 
91
 
92
+ # ---------------------------------------------------------------------
93
+ # Helper functions for web‑scraping sources
94
+ # ---------------------------------------------------------------------
95
+ def scrape_image_urls(search_url: str, max_images: int) -> list:
96
+ """Scrape image URLs from a Pinterest search page.
97
+
98
+ The function fetches the HTML of the search results, extracts ``<img>``
99
+ tags and returns up to ``max_images`` URLs that end with common image file
100
+ extensions. Pagination is handled by appending ``&page=N`` to the query URL
101
+ when needed.
102
+ """
103
+ print(f" Scraping Pinterest for up to {max_images} images …")
104
+ headers = {
105
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) "
106
+ "AppleWebKit/537.36 (KHTML, like Gecko) Chrome/124.0 Safari/537.36"
107
+ }
108
+ collected: list[str] = []
109
+ page = 1
110
+ # Initialize a headless Chrome driver for dynamic content.
111
+ chrome_options = Options()
112
+ chrome_options.add_argument("--headless")
113
+ chrome_options.add_argument("--disable-gpu")
114
+ chrome_options.add_argument("--no-sandbox")
115
+ driver = webdriver.Chrome(ChromeDriverManager().install(), options=chrome_options)
116
+
117
+ while len(collected) < max_images:
118
+ # Build the URL for the current page.
119
+ url = (
120
+ f"{search_url}&page={page}" if "page=" not in search_url else f"{search_url.split('page=')[0]}page={page}"
121
+ )
122
+ try:
123
+ driver.get(url)
124
+ # Give the page a moment to load dynamic content.
125
+ driver.implicitly_wait(3)
126
+ page_html = driver.page_source
127
+ except Exception as e:
128
+ print(f" [WARN] Selenium failed to load page {page}: {e}")
129
+ break
130
+
131
+ # Parse the rendered HTML.
132
+ soup = BeautifulSoup(page_html, "html.parser")
133
+ imgs = soup.find_all("img")
134
+ new_urls = [img.get("src") for img in imgs if img.get("src")]
135
+ # Filter duplicates and keep only image files.
136
+ new_urls = [u for u in new_urls if u not in collected and u.lower().endswith((".png", ".jpg", ".jpeg"))]
137
+ if not new_urls:
138
+ # No more new images on this page; stop pagination.
139
+ break
140
+ collected.extend(new_urls)
141
+ print(f" Found {len(collected)} image URLs so far …")
142
+ page += 1
143
+
144
+ # Clean up the driver.
145
+ driver.quit()
146
+ return collected[:max_images]
147
+
148
+
149
+ def download_images_from_urls(urls: list, save_dir: str, prefix: str, start_idx: int, target: int) -> int:
150
+ """Download, resize and save images from a list of URLs.
151
+
152
+ Mirrors the parquet pipeline: images are resized to 512×512 and saved as PNG
153
+ files named ``{prefix}_{index:05d}.png``.
154
+ """
155
+ saved = 0
156
+ for url in urls:
157
+ if saved >= target:
158
+ break
159
+ try:
160
+ resp = requests.get(url, stream=True, timeout=10)
161
+ resp.raise_for_status()
162
+ img = Image.open(resp.raw).convert("RGB")
163
+ img = img.resize((512, 512), Image.Resampling.LANCZOS)
164
+ filename = f"{prefix}_{start_idx + saved:05d}.png"
165
+ filepath = os.path.join(save_dir, filename)
166
+ img.save(filepath, "PNG")
167
+ saved += 1
168
+ if saved % 20 == 0 or saved == target:
169
+ print(f" [{prefix}] {saved}/{target} images saved …")
170
+ except Exception as e:
171
+ print(f" [warn] Failed to download {url}: {e}")
172
+ continue
173
+ return saved
174
+
175
  def crawl_source(name: str, cfg: dict, base_dataset_dir: str):
176
  """Download images for a single source category."""
177
  save_dir = os.path.join(base_dataset_dir, cfg["subdir"])
 
183
  print(f" Target : {cfg['num_images']} images")
184
  print(f"{'='*55}")
185
 
186
+ # ---------------------------------------------------------------------
187
+ # Determine source type. Parquet datasets are the default; "web" indicates
188
+ # we need to scrape image URLs.
189
+ # ---------------------------------------------------------------------
190
+ # Compute existing highest index first – needed for both flows.
191
+ existing = [f for f in os.listdir(save_dir) if f.endswith('.png') and f.startswith(cfg['prefix'])]
192
+ highest_idx = -1
193
+ for f in existing:
194
+ try:
195
+ idx = int(f.replace(cfg['prefix'] + '_', '').replace('.png', ''))
196
+ highest_idx = max(highest_idx, idx)
197
+ except ValueError:
198
+ continue
199
+ start_idx = highest_idx + 1
200
+
201
+ if cfg.get('type') == 'web':
202
+ urls = scrape_image_urls(cfg['search_url'], cfg['num_images'])
203
+ saved = download_images_from_urls(urls, save_dir, cfg['prefix'], start_idx, cfg['num_images'])
204
+ print(f"\n [OK] [{name.upper()}] Done: {saved} images saved to {save_dir}")
205
+ return saved
206
+
207
+ # Existing parquet flow
208
  df = load_parquet_safe(cfg["parquet_url"])
209
 
210
  # Try fallbacks if primary failed
datasets/realesrgan_gt/meta_info.txt CHANGED
@@ -3940,6 +3940,306 @@ face_00596.png 1
3940
  face_00597.png 1
3941
  face_00598.png 1
3942
  face_00599.png 1
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
3943
  hsr_acheron_sb_6723087.png 1
3944
  hsr_acheron_sb_6723868.png 1
3945
  hsr_acheron_sb_6723975.png 1
 
3940
  face_00597.png 1
3941
  face_00598.png 1
3942
  face_00599.png 1
3943
+ face_00600.png 1
3944
+ face_00601.png 1
3945
+ face_00602.png 1
3946
+ face_00603.png 1
3947
+ face_00604.png 1
3948
+ face_00605.png 1
3949
+ face_00606.png 1
3950
+ face_00607.png 1
3951
+ face_00608.png 1
3952
+ face_00609.png 1
3953
+ face_00610.png 1
3954
+ face_00611.png 1
3955
+ face_00612.png 1
3956
+ face_00613.png 1
3957
+ face_00614.png 1
3958
+ face_00615.png 1
3959
+ face_00616.png 1
3960
+ face_00617.png 1
3961
+ face_00618.png 1
3962
+ face_00619.png 1
3963
+ face_00620.png 1
3964
+ face_00621.png 1
3965
+ face_00622.png 1
3966
+ face_00623.png 1
3967
+ face_00624.png 1
3968
+ face_00625.png 1
3969
+ face_00626.png 1
3970
+ face_00627.png 1
3971
+ face_00628.png 1
3972
+ face_00629.png 1
3973
+ face_00630.png 1
3974
+ face_00631.png 1
3975
+ face_00632.png 1
3976
+ face_00633.png 1
3977
+ face_00634.png 1
3978
+ face_00635.png 1
3979
+ face_00636.png 1
3980
+ face_00637.png 1
3981
+ face_00638.png 1
3982
+ face_00639.png 1
3983
+ face_00640.png 1
3984
+ face_00641.png 1
3985
+ face_00642.png 1
3986
+ face_00643.png 1
3987
+ face_00644.png 1
3988
+ face_00645.png 1
3989
+ face_00646.png 1
3990
+ face_00647.png 1
3991
+ face_00648.png 1
3992
+ face_00649.png 1
3993
+ face_00650.png 1
3994
+ face_00651.png 1
3995
+ face_00652.png 1
3996
+ face_00653.png 1
3997
+ face_00654.png 1
3998
+ face_00655.png 1
3999
+ face_00656.png 1
4000
+ face_00657.png 1
4001
+ face_00658.png 1
4002
+ face_00659.png 1
4003
+ face_00660.png 1
4004
+ face_00661.png 1
4005
+ face_00662.png 1
4006
+ face_00663.png 1
4007
+ face_00664.png 1
4008
+ face_00665.png 1
4009
+ face_00666.png 1
4010
+ face_00667.png 1
4011
+ face_00668.png 1
4012
+ face_00669.png 1
4013
+ face_00670.png 1
4014
+ face_00671.png 1
4015
+ face_00672.png 1
4016
+ face_00673.png 1
4017
+ face_00674.png 1
4018
+ face_00675.png 1
4019
+ face_00676.png 1
4020
+ face_00677.png 1
4021
+ face_00678.png 1
4022
+ face_00679.png 1
4023
+ face_00680.png 1
4024
+ face_00681.png 1
4025
+ face_00682.png 1
4026
+ face_00683.png 1
4027
+ face_00684.png 1
4028
+ face_00685.png 1
4029
+ face_00686.png 1
4030
+ face_00687.png 1
4031
+ face_00688.png 1
4032
+ face_00689.png 1
4033
+ face_00690.png 1
4034
+ face_00691.png 1
4035
+ face_00692.png 1
4036
+ face_00693.png 1
4037
+ face_00694.png 1
4038
+ face_00695.png 1
4039
+ face_00696.png 1
4040
+ face_00697.png 1
4041
+ face_00698.png 1
4042
+ face_00699.png 1
4043
+ face_00700.png 1
4044
+ face_00701.png 1
4045
+ face_00702.png 1
4046
+ face_00703.png 1
4047
+ face_00704.png 1
4048
+ face_00705.png 1
4049
+ face_00706.png 1
4050
+ face_00707.png 1
4051
+ face_00708.png 1
4052
+ face_00709.png 1
4053
+ face_00710.png 1
4054
+ face_00711.png 1
4055
+ face_00712.png 1
4056
+ face_00713.png 1
4057
+ face_00714.png 1
4058
+ face_00715.png 1
4059
+ face_00716.png 1
4060
+ face_00717.png 1
4061
+ face_00718.png 1
4062
+ face_00719.png 1
4063
+ face_00720.png 1
4064
+ face_00721.png 1
4065
+ face_00722.png 1
4066
+ face_00723.png 1
4067
+ face_00724.png 1
4068
+ face_00725.png 1
4069
+ face_00726.png 1
4070
+ face_00727.png 1
4071
+ face_00728.png 1
4072
+ face_00729.png 1
4073
+ face_00730.png 1
4074
+ face_00731.png 1
4075
+ face_00732.png 1
4076
+ face_00733.png 1
4077
+ face_00734.png 1
4078
+ face_00735.png 1
4079
+ face_00736.png 1
4080
+ face_00737.png 1
4081
+ face_00738.png 1
4082
+ face_00739.png 1
4083
+ face_00740.png 1
4084
+ face_00741.png 1
4085
+ face_00742.png 1
4086
+ face_00743.png 1
4087
+ face_00744.png 1
4088
+ face_00745.png 1
4089
+ face_00746.png 1
4090
+ face_00747.png 1
4091
+ face_00748.png 1
4092
+ face_00749.png 1
4093
+ face_00750.png 1
4094
+ face_00751.png 1
4095
+ face_00752.png 1
4096
+ face_00753.png 1
4097
+ face_00754.png 1
4098
+ face_00755.png 1
4099
+ face_00756.png 1
4100
+ face_00757.png 1
4101
+ face_00758.png 1
4102
+ face_00759.png 1
4103
+ face_00760.png 1
4104
+ face_00761.png 1
4105
+ face_00762.png 1
4106
+ face_00763.png 1
4107
+ face_00764.png 1
4108
+ face_00765.png 1
4109
+ face_00766.png 1
4110
+ face_00767.png 1
4111
+ face_00768.png 1
4112
+ face_00769.png 1
4113
+ face_00770.png 1
4114
+ face_00771.png 1
4115
+ face_00772.png 1
4116
+ face_00773.png 1
4117
+ face_00774.png 1
4118
+ face_00775.png 1
4119
+ face_00776.png 1
4120
+ face_00777.png 1
4121
+ face_00778.png 1
4122
+ face_00779.png 1
4123
+ face_00780.png 1
4124
+ face_00781.png 1
4125
+ face_00782.png 1
4126
+ face_00783.png 1
4127
+ face_00784.png 1
4128
+ face_00785.png 1
4129
+ face_00786.png 1
4130
+ face_00787.png 1
4131
+ face_00788.png 1
4132
+ face_00789.png 1
4133
+ face_00790.png 1
4134
+ face_00791.png 1
4135
+ face_00792.png 1
4136
+ face_00793.png 1
4137
+ face_00794.png 1
4138
+ face_00795.png 1
4139
+ face_00796.png 1
4140
+ face_00797.png 1
4141
+ face_00798.png 1
4142
+ face_00799.png 1
4143
+ face_00800.png 1
4144
+ face_00801.png 1
4145
+ face_00802.png 1
4146
+ face_00803.png 1
4147
+ face_00804.png 1
4148
+ face_00805.png 1
4149
+ face_00806.png 1
4150
+ face_00807.png 1
4151
+ face_00808.png 1
4152
+ face_00809.png 1
4153
+ face_00810.png 1
4154
+ face_00811.png 1
4155
+ face_00812.png 1
4156
+ face_00813.png 1
4157
+ face_00814.png 1
4158
+ face_00815.png 1
4159
+ face_00816.png 1
4160
+ face_00817.png 1
4161
+ face_00818.png 1
4162
+ face_00819.png 1
4163
+ face_00820.png 1
4164
+ face_00821.png 1
4165
+ face_00822.png 1
4166
+ face_00823.png 1
4167
+ face_00824.png 1
4168
+ face_00825.png 1
4169
+ face_00826.png 1
4170
+ face_00827.png 1
4171
+ face_00828.png 1
4172
+ face_00829.png 1
4173
+ face_00830.png 1
4174
+ face_00831.png 1
4175
+ face_00832.png 1
4176
+ face_00833.png 1
4177
+ face_00834.png 1
4178
+ face_00835.png 1
4179
+ face_00836.png 1
4180
+ face_00837.png 1
4181
+ face_00838.png 1
4182
+ face_00839.png 1
4183
+ face_00840.png 1
4184
+ face_00841.png 1
4185
+ face_00842.png 1
4186
+ face_00843.png 1
4187
+ face_00844.png 1
4188
+ face_00845.png 1
4189
+ face_00846.png 1
4190
+ face_00847.png 1
4191
+ face_00848.png 1
4192
+ face_00849.png 1
4193
+ face_00850.png 1
4194
+ face_00851.png 1
4195
+ face_00852.png 1
4196
+ face_00853.png 1
4197
+ face_00854.png 1
4198
+ face_00855.png 1
4199
+ face_00856.png 1
4200
+ face_00857.png 1
4201
+ face_00858.png 1
4202
+ face_00859.png 1
4203
+ face_00860.png 1
4204
+ face_00861.png 1
4205
+ face_00862.png 1
4206
+ face_00863.png 1
4207
+ face_00864.png 1
4208
+ face_00865.png 1
4209
+ face_00866.png 1
4210
+ face_00867.png 1
4211
+ face_00868.png 1
4212
+ face_00869.png 1
4213
+ face_00870.png 1
4214
+ face_00871.png 1
4215
+ face_00872.png 1
4216
+ face_00873.png 1
4217
+ face_00874.png 1
4218
+ face_00875.png 1
4219
+ face_00876.png 1
4220
+ face_00877.png 1
4221
+ face_00878.png 1
4222
+ face_00879.png 1
4223
+ face_00880.png 1
4224
+ face_00881.png 1
4225
+ face_00882.png 1
4226
+ face_00883.png 1
4227
+ face_00884.png 1
4228
+ face_00885.png 1
4229
+ face_00886.png 1
4230
+ face_00887.png 1
4231
+ face_00888.png 1
4232
+ face_00889.png 1
4233
+ face_00890.png 1
4234
+ face_00891.png 1
4235
+ face_00892.png 1
4236
+ face_00893.png 1
4237
+ face_00894.png 1
4238
+ face_00895.png 1
4239
+ face_00896.png 1
4240
+ face_00897.png 1
4241
+ face_00898.png 1
4242
+ face_00899.png 1
4243
  hsr_acheron_sb_6723087.png 1
4244
  hsr_acheron_sb_6723868.png 1
4245
  hsr_acheron_sb_6723975.png 1
requirements.txt CHANGED
@@ -8,6 +8,8 @@ attrs==26.1.0
8
  audioop-lts==0.2.2
9
  # basicsr (installed via patch_and_install_basicsr.py)
10
  beautifulsoup4==4.15.0
 
 
11
  blinker==1.9.0
12
  brotli==1.2.0
13
  cachetools==7.1.4
 
8
  audioop-lts==0.2.2
9
  # basicsr (installed via patch_and_install_basicsr.py)
10
  beautifulsoup4==4.15.0
11
+ selenium==4.21.0
12
+ webdriver-manager==4.0.2
13
  blinker==1.9.0
14
  brotli==1.2.0
15
  cachetools==7.1.4