From 7dc98330bcb02e6aaba29e8a644695b36f50cc54 Mon Sep 17 00:00:00 2001 From: fishermanykx Date: Mon, 12 Jul 2021 16:02:26 +0800 Subject: [PATCH] Fix some bug in Spider --- src/backend/Data_Cleansing/createTestDB.sql | 252 ++++++++++++++++++ src/backend/Data_Cleansing/data_cleansing.py | 6 +- src/backend/JDSpiders/Spider/JDSpider.py | 79 ++++-- .../__pycache__/DBConfig.cpython-37.pyc | Bin 0 -> 473 bytes .../__pycache__/DBConfig.cpython-38.pyc | Bin 0 -> 435 bytes .../JDSpider.cpython-37-PYTEST.pyc | Bin 0 -> 31689 bytes .../__pycache__/dataCleaning.cpython-37.pyc | Bin 0 -> 21251 bytes 7 files changed, 307 insertions(+), 30 deletions(-) create mode 100644 src/backend/Data_Cleansing/createTestDB.sql create mode 100644 src/backend/JDSpiders/Spider/__pycache__/DBConfig.cpython-37.pyc create mode 100644 src/backend/JDSpiders/Spider/__pycache__/DBConfig.cpython-38.pyc create mode 100644 src/backend/JDSpiders/Spider/__pycache__/JDSpider.cpython-37-PYTEST.pyc create mode 100644 src/backend/JDSpiders/Spider/__pycache__/dataCleaning.cpython-37.pyc diff --git a/src/backend/Data_Cleansing/createTestDB.sql b/src/backend/Data_Cleansing/createTestDB.sql new file mode 100644 index 0000000..0208b50 --- /dev/null +++ b/src/backend/Data_Cleansing/createTestDB.sql @@ -0,0 +1,252 @@ +CREATE DATABASE IF NOT EXISTS test; +USE test; + +DROP TABLE IF EXISTS `cpu`; +CREATE TABLE `cpu` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `comment_num` INT DEFAULT 100, + `praise_rate` INT DEFAULT 90, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `brand` varchar(255) DEFAULT NULL, + `tags` varchar(255) DEFAULT NULL, + `clock_speed` varchar(255) DEFAULT NULL, + `core_num` varchar(255) DEFAULT NULL, + `TDP` INT DEFAULT 0, + `socket` varchar(255) DEFAULT NULL, + `have_core_graphics_card` varchar(255) DEFAULT NULL, + `have_cpu_fan` varchar(255) DEFAULT NULL, + `generation` INT DEFAULT 0, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate cpu; + +DROP TABLE IF EXISTS `motherboard`; +CREATE TABLE `motherboard` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `comment_num` INT DEFAULT 100, + `praise_rate` INT DEFAULT 90, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `brand` varchar(255) DEFAULT NULL, + `tags` varchar(255) DEFAULT NULL, + `form_factor` varchar(255) DEFAULT NULL, + `platform` varchar(255) DEFAULT NULL, + `cpu_socket` varchar(255) DEFAULT NULL, + `m2_num` INT DEFAULT 0, + `slot_num` INT DEFAULT 0, + `ddr_gen` varchar(255) DEFAULT NULL, + `max_memory` INT DEFAULT 0, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate motherboard; + +DROP TABLE IF EXISTS `graphics_card`; +CREATE TABLE `graphics_card` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `comment_num` INT DEFAULT 100, + `praise_rate` INT DEFAULT 90, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `brand` varchar(255) DEFAULT NULL, + `tags` varchar(255) DEFAULT NULL, + `card_length` float DEFAULT 0, + `rgb` varchar(255) DEFAULT NULL, + `card_type` varchar(255) DEFAULT NULL, + `generation` INT DEFAULT 0, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate graphics_card; + +DROP TABLE IF EXISTS `memory`; +CREATE TABLE `memory` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `comment_num` INT DEFAULT 100, + `praise_rate` INT DEFAULT 90, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `brand` varchar(255) DEFAULT NULL, + `frequency` varchar(255) DEFAULT NULL, + `total_capacity` INT DEFAULT 0, + `memory_num` varchar(255) DEFAULT NULL, + `appearance` varchar(255) DEFAULT NULL, + `ddr_gen` varchar(255) DEFAULT NULL, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate memory; + +DROP TABLE IF EXISTS `cpu_radiator`; +CREATE TABLE `cpu_radiator` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `comment_num` INT DEFAULT 100, + `praise_rate` INT DEFAULT 90, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `brand` varchar(255) DEFAULT NULL, + `height` INT DEFAULT 0, + `socket` varchar(255) DEFAULT NULL, + `radiator_size` INT DEFAULT 0, + `rgb` varchar(255) DEFAULT NULL, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate cpu_radiator; + +DROP TABLE IF EXISTS `ssd`; +CREATE TABLE `ssd` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `comment_num` INT DEFAULT 100, + `praise_rate` INT DEFAULT 90, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `brand` varchar(255) DEFAULT NULL, + `interface` varchar(255) DEFAULT NULL, + `total_capacity` FLOAT DEFAULT 0, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate ssd; + +DROP TABLE IF EXISTS `hdd`; +CREATE TABLE `hdd` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `comment_num` INT DEFAULT 100, + `praise_rate` INT DEFAULT 90, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `brand` varchar(255) DEFAULT NULL, + `size` varchar(255) DEFAULT NULL, + `rotating_speed` varchar(255) DEFAULT NULL, + `total_capacity` FLOAT DEFAULT 0, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate hdd; + +DROP TABLE IF EXISTS `power_supply`; +CREATE TABLE `power_supply` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `comment_num` INT DEFAULT 100, + `praise_rate` INT DEFAULT 90, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `brand` varchar(255) DEFAULT NULL, + `tags` varchar(255) DEFAULT NULL, + `power` INT DEFAULT 0, + `size` varchar(255) DEFAULT NULL, + `modularization` varchar(255) DEFAULT NULL, + `transfer_efficiency` varchar(255) DEFAULT NULL, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate power_supply; + +DROP TABLE IF EXISTS `computer_case`; +CREATE TABLE `computer_case` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `comment_num` INT DEFAULT 100, + `praise_rate` INT DEFAULT 90, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `brand` varchar(255) DEFAULT NULL, + `max_form_factor` varchar(255) DEFAULT NULL, + `max_card_len` INT DEFAULT 0, + `max_radiator_height` INT DEFAULT 0, + `supported_radiator` varchar(255) DEFAULT NULL, + `has_transparent_side_panel` INT DEFAULT 0, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate computer_case; + +DROP TABLE IF EXISTS `board_u_suit`; +CREATE TABLE `board_u_suit` ( + `id` int(11) DEFAULT 0, + `name` varchar(255) DEFAULT NULL, + `board` varchar(255) DEFAULT NULL, + `cpu` varchar(255) DEFAULT NULL, + `shop_name` varchar(255) DEFAULT NULL, + `price` INT DEFAULT 0, + `link` varchar(255) NOT NULL, + `introduction` JSON, + `Ptable_params` JSON, + `title_name` varchar(255) DEFAULT NULL, + PRIMARY KEY (`link`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate board_u_suit; + +DROP TABLE IF EXISTS `trendings`; +CREATE TABLE `trendings` ( + `id` varchar(255) NOT NULL, + `frequency` int(11) DEFAULT 0, + `cpu` varchar(255) NOT NULL, + `cpu_price` int(11) DEFAULT 0, + `cpu_link` varchar(255) NOT NULL, + `motherboard` varchar(255) NOT NULL, + `motherboard_price` int(11) DEFAULT 0, + `motherboard_link` varchar(255) NOT NULL, + `GPU` varchar(255) NOT NULL, + `GPU_price` int(11) DEFAULT 0, + `GPU_link` varchar(255) NOT NULL, + `memory` varchar(255) NOT NULL, + `memory_price` int(11) DEFAULT 0, + `memory_link` varchar(255) NOT NULL, + `CPURadiator` varchar(255) NOT NULL, + `CPURadiator_price` int(11) DEFAULT 0, + `CPURadiator_link` varchar(255) NOT NULL, + `ssd` varchar(255) NOT NULL, + `ssd_price` int(11) DEFAULT 0, + `ssd_link` varchar(255) NOT NULL, + `hdd` varchar(255) NOT NULL, + `hdd_price` int(11) DEFAULT 0, + `hdd_link` varchar(255) NOT NULL, + `powerSupply` varchar(255) NOT NULL, + `powerSupply_price` int(11) DEFAULT 0, + `powerSupply_link` varchar(255) NOT NULL, + `case` varchar(255) NOT NULL, + `case_price` int(11) DEFAULT 0, + `case_link` varchar(255) NOT NULL, + `totalPrice` int(11) DEFAULT 0, + PRIMARY KEY (`id`) +) ENGINE=InnoDB AUTO_INCREMENT=38 DEFAULT CHARSET=utf8mb4, COLLATE=utf8mb4_general_ci; +truncate trendings; \ No newline at end of file diff --git a/src/backend/Data_Cleansing/data_cleansing.py b/src/backend/Data_Cleansing/data_cleansing.py index 9074beb..b7ac932 100644 --- a/src/backend/Data_Cleansing/data_cleansing.py +++ b/src/backend/Data_Cleansing/data_cleansing.py @@ -331,7 +331,7 @@ class DataCleaning: " modify card_length float default 0.0" row = cursor.execute(instruct) # 返回被影响的行数 # 重新写入 - sql_insert = "INSERT INTO video_card (id, name, comment_num, praise_rate, shop_name, price, link,"\ + sql_insert = "INSERT INTO graphics_card (id, name, comment_num, praise_rate, shop_name, price, link,"\ "brand, tags, card_length, rgb, card_type, introduction, Ptable_params) VALUES (%(id)s, %(name)s, %(comment_num)s,"\ "%(praise_rate)s, %(shop_name)s, %(price)s, %(link)s, %(brand)s, %(tags)s, %(card_length)s, "\ "%(rgb)s, %(card_type)s, %(introduction)s, %(Ptable_params)s)" @@ -1029,7 +1029,7 @@ class DataCleaning: self.cleanCPU() elif t == 'motherboard': self.cleanMotherboard() - elif t == 'video_card': + elif t == 'graphics_card': self.cleanGraphicsCard() elif t == 'cpu_radiator': self.cleanCPURadiator() @@ -1050,6 +1050,6 @@ class DataCleaning: if __name__ == "__main__": # washer = DataCleaning('power_supply') - washer = DataCleaning('video_card') + washer = DataCleaning('graphics_card') # washer = DataCleaning('motherboard') washer.main() diff --git a/src/backend/JDSpiders/Spider/JDSpider.py b/src/backend/JDSpiders/Spider/JDSpider.py index bc1015b..b67bd4e 100644 --- a/src/backend/JDSpiders/Spider/JDSpider.py +++ b/src/backend/JDSpiders/Spider/JDSpider.py @@ -10,6 +10,7 @@ import re import json import time import pymysql +from pymysql.converters import escape_string from selenium.common.exceptions import ElementNotInteractableException from selenium.common.exceptions import ElementClickInterceptedException @@ -553,13 +554,19 @@ class CPUSpider(JDSpider): # 时钟频率 record['clock_speed'] = p_table['规格']['主频'] # 内核数 - record['core_num'] = introd['核心数量'] + try: + record['core_num'] = introd['核心数量'] + except: + record['core_num'] = introd['核心数'] # 是否支持核显 record['have_core_graphics_card'] = introd.get('是否支持核显', '不支持核显') # 是否自带风扇 record['have_cpu_fan'] = introd.get('是否自带风扇', '不带风扇') # TDP - record['TDP'] = int(p_table['规格']['功率'][:-1]) + try: + record['TDP'] = int(p_table['规格']['功率'][:-1]) + except: + record['TDP'] = -1 # 处理接口 socket = introd["接口"] if "1151" in socket: @@ -569,7 +576,8 @@ class CPUSpider(JDSpider): record["socket"] = socket # CPU 代数 - # 分类标准:锐龙5000系和酷睿10代为最新代;锐龙3000和酷睿9代为上代;其余为上古版本 + # 分类标准: + # 鉴于 Intel 11 代倒吸牙膏,认定锐龙5000系和酷睿10代为最新代;锐龙3000和酷睿11代或9代为上代;其余为上古版本 # 提取代数 name = record['name'] pat = r"\d+\w" @@ -578,6 +586,8 @@ class CPUSpider(JDSpider): if record['brand'] == 'INTEL': if res[:2] == "10": record['generation'] = 3 + elif res[:2] == '11': + record['generation'] = 2 elif res[0] == '9': record['generation'] = 2 else: @@ -647,9 +657,9 @@ class CPUSpider(JDSpider): cpu_link = "https://list.jd.com/list.html?cat=670%2C677%2C678&page=" cpu_link = "https://list.jd.com/list.html?cat=670%2C677%2C678&psort=3&psort=3&page=" - page_num = 3 + page_num = 1 start_page = 1 - self.productSpider(cpu_link, page_num, start_page) + # self.productSpider(cpu_link, page_num, start_page) self.cleanCPU() print("Successfully get CPU data!") @@ -757,7 +767,10 @@ class MotherboardSpider(JDSpider): print(introd) exit(1) # 加入 m2 接口数 列 - record['m2_num'] = int(introd.get('M.2接口数量', 0)) + try: + record['m2_num'] = int(introd.get('M.2接口数量', 0)) + except: + record['m2_num'] = int(introd.get('M.2接口数量', "00")[:-1]) # 插槽数目 slot_num = p_table['内存'].get("内存插槽", 0) try: @@ -811,9 +824,13 @@ class MotherboardSpider(JDSpider): # 判定是否为板-U套装 record = data[i] if record['comment_num'] == 100: # 抓到板-U套装了 - continue - if '套装' in record['title_name']: - continue + continue + try: + if '套装' in record['title_name']: + continue + except: + if '套装' in record['name']: + continue # 清洗数据 new_data.append(self.handleSingleMotherboardRecord(record)) new_data[index]['id'] = cnt @@ -833,12 +850,12 @@ class MotherboardSpider(JDSpider): connection.commit() def main(self): - motherboard_link = "https://list.jd.com/list.html?cat=670%2C677%2C681&psort=3&psort=3&page=" + motherboard_link = "https://list.jd.com/list.html?cat=670%2C677%2C681&psort=3&psort=3&pvid=e726d0ee460448b6a16cf24950c1dabb&page=" # 爬取数据 - page_num = 26 # 一共爬了26页 - # page_num = 1 # for testing + # page_num = 26 # 一共爬了26页 + page_num = 1 # for testing start_page = 1 - self.productSpider(motherboard_link, page_num, start_page) + # self.productSpider(motherboard_link, page_num, start_page) # 清洗数据 self.cleanMotherboard() print("Successfully get Motherboard data!") @@ -997,9 +1014,10 @@ class GraphicsCardSpider(JDSpider): connection.commit() def main(self): - graphics_card_link = "https://list.jd.com/list.html?cat=670%2C677%2C679&psort=3&psort=3&page=" + graphics_card_link = "https://list.jd.com/list.html?cat=670%2C677%2C679&psort=3&psort=3&pvid=e726d0ee460448b6a16cf24950c1dabb&page=" # 爬取数据 - page_num = 30 + # page_num = 30 + page_num = 1 start_page = 1 # self.productSpider(graphics_card_link, page_num, start_page) # 清洗数据 @@ -1169,17 +1187,18 @@ class MemorySpider(JDSpider): "Ptable_params, title_name) VALUES (%(id)s, %(name)s, %(comment_num)s, %(praise_rate)s, %(shop_name)s, %(price)s"\ ", %(link)s, %(brand)s, %(frequency)s, %(total_capacity)s, %(memory_num)s, %(appearance)s, "\ "%(ddr_gen)s, %(introduction)s, %(Ptable_params)s, %(title_name)s)" - sql_insert = pymysql.escape_string(sql_insert) - cursor.executemany(sql_insert, new_data) - # for i in range(len(new_data)): - # cursor.execute(sql_insert, new_data[i]) + # sql_insert = escape_string(sql_insert) + # cursor.executemany(sql_insert, new_data) + for i in range(len(new_data)): + cursor.execute(sql_insert, new_data[i]) connection.commit() def main(self): memory_link = "https://list.jd.com/list.html?cat=670%2C677%2C680&psort=3&ev=210_1558%5E&psort=3&page=" # 爬取数据 - page_num = 40 + # page_num = 40 + page_num = 1 start_page = 1 # self.productSpider(memory_link, page_num, start_page) # 清洗数据 @@ -1366,9 +1385,10 @@ class CPURadiatorSpider(JDSpider): def main(self): radiator_link = "https://list.jd.com/list.html?cat=670%2C677%2C682&psort=3&ev=3680_97402%7C%7C97403%7C%7C106254%7C%7C106255%5E&psort=3&page=" # 爬取数据 - page_num = 27 + # page_num = 27 + page_num = 1 start_page = 1 - # self.productSpider(radiator_link, page_num, start_page) + self.productSpider(radiator_link, page_num, start_page) # 清洗数据 self.cleanCPURadiator() print("Successfully get CPU Radiator data!") @@ -1538,7 +1558,8 @@ class SSDSpider(JDSpider): def main(self): ssd_link = "https://list.jd.com/list.html?cat=670%2C677%2C11303&psort=3&psort=3&page=" - page_num = 36 # 一共爬了36页 + # page_num = 36 # 一共爬了36页 + page_num = 1 # 一共爬了36页 start_page = 1 # self.productSpider(ssd_link, page_num, start_page) @@ -1715,7 +1736,8 @@ class HDDSpider(JDSpider): def main(self): hdd_link = "https://list.jd.com/list.html?cat=670%2C677%2C683&psort=3&psort=3&page=" - page_num = 11 + # page_num = 11 + page_num = 1 start_page = 1 # self.productSpider(hdd_link, page_num, start_page) @@ -1871,7 +1893,8 @@ class PowerSupplySpider(JDSpider): def main(self): power_supply_link = "https://list.jd.com/list.html?cat=670%2C677%2C691&psort=3&psort=3&page=" - page_num = 25 # 抓25页 + # page_num = 25 # 抓25页 + page_num = 1 start_page = 1 # self.productSpider(power_supply_link, page_num, start_page) @@ -2056,9 +2079,10 @@ class CaseSpider(JDSpider): def main(self): case_link = "https://list.jd.com/list.html?cat=670%2C677%2C687&psort=3&psort=3&page=" - page_num = 36 + # page_num = 36 + page_num = 1 start_page = 1 - self.productSpider(case_link, page_num, start_page) + # self.productSpider(case_link, page_num, start_page) self.cleanCase() print("Successfully get Computer Case data!") @@ -2066,6 +2090,7 @@ class CaseSpider(JDSpider): if __name__ == "__main__": accessory_type = 'all' + accessory_type = 'motherboard' if accessory_type == 'cpu': cpu_spider = CPUSpider('cpu') cpu_spider.main() diff --git a/src/backend/JDSpiders/Spider/__pycache__/DBConfig.cpython-37.pyc b/src/backend/JDSpiders/Spider/__pycache__/DBConfig.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..d7ad420a0393dec505f6778ff9f15fde9a5dedc5 GIT binary patch literal 473 zcmZWl%}T>S5KjMWjn=alAy*Gdeyr6XV%tUVP^Uc8Uwd-|VQ?~K?iN92Sn>Pz9sNzV4SXV$aUn2#-K#G2ml>8DY z`(;u=+UC;iS@%FhoK7TViEDVF42^au!051KM8_!)=Y-x$@HkAS_fNW7 z2G_7n+uXA3EypyhhU+-4)6~yGA-jZ1#>JnT1v8}a|Jz-6$JA%bmfhSom0MYvGba6- zxo123rq!VDtD1JPS;?vx6Bc2dt(@PW%QJk^LqnA5d2@xjgKRCY`z?g7djoI5^?QTi zi^i);lppwb^4y@q;z=rjV-!(HA_x#0$;Xfb?j~cJ0C1X&f45pu1VS)QLEr&IERG=| xKQdu76%yj$HjM7oEI9Shgc9H)$aCPeb6K}1)2wz7Gm<{Q;rtmYwVEmkqyGE-m#7~(`D?Nu=OU9M0Z4KsB)c-&ad%M3Eg{8K zP#H+|-Oa1&;3Qxq=7dJJ=0Fa$9!#*-r_q8urVQqS+D-YAGF!VK$r7^=M(fp!Du%JG znYyVr46|YBn$fZ?%eLC;5GH(p2&XLhx3g7dBrJA~hTdwJ9nCOo5yz&w*)z;`Qx|Sz z3Zs;}RlQ?cC%Vxhp9hjOs+Y5h?;{%cezt#o2X2P`2(hW#!JmW1Pgrwn@!Fj(OTc~=gI i3BoM#it0JN;#kdiomEdmiqa>1mOmh=3Q#JFocj-~%6ruS literal 0 HcmV?d00001 diff --git a/src/backend/JDSpiders/Spider/__pycache__/JDSpider.cpython-37-PYTEST.pyc b/src/backend/JDSpiders/Spider/__pycache__/JDSpider.cpython-37-PYTEST.pyc new file mode 100644 index 0000000000000000000000000000000000000000..eed40b7acb3e09e4b9fcbdfeb439a2c2df1510a7 GIT binary patch literal 31689 zcmeHwd2k!onJ3V=8XyQBqNvk0tSh1{lN5C;cA|rlEL)~D5@kEEG%$qMBq4zS)o55E z0yuVL$?_ptj*s||ZPI5F+p^i6FFeZTMPhmEzhf#3YMe~do)XAZ~zblCpf@UO>} zdCci>2uH*roI*)DBMRSL{cgqKbo6^7UZ+g)MSPs1MpVB0BYwUIA_3f8$(sIPB*=N) z@YhCa+3$fr6bZ54o2=`vkJPi@mu%>7j5M-eO-}2d7MaF=f3m6DAp()bXhOJ&!?O{dE}9W;=I|VC zu9$I9IqlR>h?$XVv}?pH4$anPh*?LSk!!VUhprn&|5GWX&E~XK+DtJUX<;pFrR_r6 z98TM%%@T8vcD;7Jm9`3Lb2%-g%@%W!Hcy*prOig#OinwY%@H$^HeZ`B(}c3y(Q-|0 zFwm)G;(B7hNTgHi0vobMUs_)m-jc}lX?lMwHF)qypfhG@>%txF9ql(R>$tIFZMc2S zx{hV*RxAr_k7bO_B4MQU%(!PtDcy;F`RuYA+wp%@xMTUc6>HWlZx4*o4C!idn%8Yk zYW-Tu=t>*gQii6-;zn$LQrmnau5qi7C2VEcluX1AawbaCggsAlS9*6g-e={sr}%bo zIT;k>KdkK+dg5M9N5DHUpeIrWe9k42rg*x4AdBjwv3Oj|WYT&914C^r{VDLQ$CbGY zj^>CsF_kfeBQBu`*Mp9TTeyV>caQK2AMReE3P0{X5fC-Ft0E|BarcXmsKY%V>O}+Y zHKI{W!#yaP@Jgne>aCr-2NFWlv$tct1j6{cc;fBR=ia*b%a1QU|KPjljyiDX_nL4P zl)U4BYY1;QuM8_rhv7Nkr5NEkNx6Ljp{Oc+P2Pv``hp5+6MG=Pa>(cVwuHyH4znBPb`}>qVY7A0R}yz8Ac-2n`uq-BRw-l zjW<05y4FKe*_W2HdJL1qG4>CX=FS>DYg)XfyDyzFO!q)qhnvl4I;MIolQ}F*MeH|y z@xGXjvRfL=P-(6YMvcJ%%?t=F8G|2-R`;O9NGRT?r~9?2Raaz2Oo*s7OxL2DQ@x3lhK{6qE4emQ)_!!CCTG8h(Ik%U z9?Te8|K9zv_(3ft_LdfDX0KeV<%rgSK~s%J6RCs|jV?kvGGRClr`PFKRHy0;IqMbj zyPZn;pX$mrlnQJuJsYPNOMi5ych8e`COifv)B)#Fr<3l=kc;RCPcLT|h6FQ&R^Ro= zs8ep!6HlfyT8mSkM^Q91(pf->z9{BhG8(-ZfebARhZ1n+>TRvzm&JEZW3Q9D92dwtNce|K3gL?{oGTvtv*P1F#0PhOBaf{fY{OJ+2FI2%Nh?VHY)ZXTl+7Y~~0rk&38 zmp8rfqv+>J2|^j$h=MY-8XR8L>2~HC%OhFN66aw?4thHwT>N7H2_xI@}4G#P>|xB;VAg>?ja@b8^&ZfH1kf!Y1fgr z^X^XE_q~EN-nnF|;TfWRi*s_kDqQpw#nZlbz}MuUu$AVXEDh~bartotPAf;AF&x5k z)QQ@ZeJ2WNTcPI2U*>Cw*%|y(;Vsk*F5=Ss!YA7<+bq->sA(u5{KL*d@J>gn)rkpg z)jU3Lz@GO9j+Anj<4(t+|KN5QH3tKz=|TA{>aOLwg0vW{K3sACet?qi!gZ&^sLcnD zIz^393%1bNG3W+HvUI zo%Hq_hZMX)^{A8LXr9Ut&DDL!v6j@lcb22jkoWVwJ|EzFh{w#GZ{QxyM!%;GJNEht zb%n;lv_ey1dZD>611(xmep9n-Eoz_^opv1-vJZH=38U7SpOz2h>+=oyru_7LbAHBf zfN~uYn8ml=DYxy}U3vi9fL;qHxB74*CDMmm!Ih_z$?o*x_NC$F;U!^_j%SJHw(d`h zK`ZqZEz#R&gxkU^TE08!gDWrf;HsAIj@?9c6OqZSZ0j@nlWkN(n@HSy_v(FgV{Zq0 z?_O3FlTEfI6L;rAmB{7$+F}uRA9$2pxEwpNfV(N*7}1j4!al*Q3w`W{YZUZ^go*2um0Nw!tt&s(lT9)EPNTIoofesGsh)HtbGoOh(HJ+#E*^0I zy_)GlYfW!#U;tw%c@P&0G2O&inx0Hj(+2bzc=?f#c0`Lq>WWGk)STXf$sg6EKp5RW z7(Fr&Gx{R6csd$03_Y=*L^PtGrVn#W*D`&kE2*V)Vzf}ccEr$cAg_n}$4rnJw0FP^ zCQ{&tjaxg3TDQz(`W{iy{ivQ!8>UL{gXA4EkTGJq0imT=i&%c-%0O<@l17ZzQ+{2fvDcu14Hd@U6tXdX+Gzg`6{$dc*`O`JJuRYWnb%3xE)pww5(ofq`deSM84U`CDQ_~kTcg@=C-Q3SZ1YXp_e{f z%yC7)$Aa5(;!<$Aa549VJ2;{OK&XP60Jnn+z*C_H)WI6`n%qNcZ4+nJ*tS-1!jkXnE!h@JwC4ZV2cAo~h5*3(qVE=uf@y&2rr2$cKby zwSzc^L%Sq(+35f`vJ2eEt~(uri>qfojNl&Q(0{eBSueREor zh;wKDkEqEz4|?@~&ReN@>XYR+yhFY`@ne2N9rB~xfC!fPLF#oaIJTN$@K%$i2LCLX9*YyKXS%Nxreo}y6AsYf={Gr! z+&9=aN#2GT4m{gTBPtrL=Vn|YpX7^_!p!_kDjOp{17qFHW8IAL0$fP{Xsn5|JncO6 z40vegp?kmq(uf4mt3av8#1-JJ*MTQc3QECM6%Q#09J?EDG?1_9@j(u1%EmC$SiF$p zM)CenfKzZp_>%a_W#A}b{xco9?~fzfOPE9u)gU4+N%pu9BC|g2>}&PpS<|yds&h@i;oNe)Y-Xx z&+ZGKJYRg`S!SVfZR0APbSSv<)bNgdxmB0*fHjhp0bP>2p{;Gn-Rl$L=6OOhVu|Fu zsxhzRq&JXr?`!K@o>P$}iT@lH2E_`|QqKfZUyUy5>)@Dycv6d{HWH4ecTj{UGmuPx zdLGE6Q>I5``v)@mO3J>99HOHn;sY6tG~3B%rc6KewUlugWt;(8xGAgaU?c&JFzlM` z-w!x+mP7}L3h7(O*-FkW^o-kx^=1Goqz?m0a%U1bEi%nO^D;d^OSPV!1Vbx>`Zjvv zR&s8G6Y=+eV*!d~=n<7r6ZTmo3-E~0jznq>YJ*Y8#hm1`0+FCa$cQ1#MCw7_qxKkm zJxV7;i@-$FLr*0lz5!XJ>C0sIM-dlc56T`#{B+`W{~A~35jYMHlQkl3_J1xfh*7{L z;0zCu;I}`#91YN|=tI{4jOp1%zF5Yk= zE(i)a*V^`l`i&TpD_s36_KguIY1>{#-+l1H#~)r{F)R1wHhtkH0-=C*feD+4l%CdN z3ytm9lDUmvp%Cn7BzKJcEBO zO5+q~qmm2TSIT6YS)8C?`Xf3)$R4wMzlFyDZfYoo%WxYW15BP!0MOUuYlbih!Nj>R z0Rc`4H-I&Qll+*HlB|33-nzwoXG zMjG|!g9n1d^a(GP-f=)lK7t5Rvk{{r=2^t}IYxyqKt8Y}b0tfHm>P-!OXa1z#mWVT zLbO~^AKyig7DMhvW-6-C)@>~1gaKa1NEwq3vkHdu>2(;17OzgDqc@P#NX|5Jn#h?B zCl}n-1t7jVysfKyM>wW{R}L>uK(q5D6+@TiXCPXVG|v)COZbir+xKkV9bUW;m9}J- zh8HfTilxsc7s&{lY$PMf0#_*=Qm^!qWF>vvBI&iuQ8K1VmXcAn)@53DbcH+j?A*R> z(}wQN;oCODV-&&n%3MBIH{`d-wQtJy1-EZ*DN@_pPZ^2LR74<+jH62=7bw0KMxX1S^8 zz?J%AM!e5-YZy$^)2pYm1K8yFJ<*skLuephx3Jc^@*Kq*11+=m6G0 zETDq1B0|)}B*=y_R1w0mZkdE2x_H>$M`6&e(BN1aGWO3TOe{i3Eo;q3?q5!OX5hi^hSbWq9s8238F zKO*WmegVP_2tO|xIoyQsG=zU4nmCM?D5fKPPBa&sseeKUrYrhiikS$FA_UVF{kLK^ zLMB2mNYVdJ%th$05V{7TzZcgc^ch0evC)Y`gb_ZA@bw(77xNH)3E}x14vPf{pF(&c zhug&>gzrQ6I~-mw79*TOxP`+z#S(=76yX~;4Yzk%;_V6E za=O_*20-9JXcbR%8^8PH;fT`R&CKM*Q$H`B{h;{5r^WMcWN8HzPoBCs{4~$%h;Ngg zjVG|){YV&n^p_W3{CxDY&mzh#J2~sf(V>y&&PKf1E!c8I#GB}$yG(lKqmg%Bg{T8{ zG!)meR}NlC=K$v9V(xMqGF8+{#(en&OG)Bi`-X zHgs*@CX0LEsp2CqMAVH5V~dtb9O1}|54<&Y?&Vx)3mXC@!>~_E^rmFNCyp0CeWm!} z>!S~!j|6Yu+`VBtDDc+J8+P$vV%$*N*gH=}g4Wy7Nj)NKKk@UC_nwG&Q|Y*Y!Jx6f z_}E*;*M2qj(R&ef=PeuXmT%iF-^u5nj=g$n^!{TJ&#ilI*&)Z`;;Cnfr%y!OTQ_gp z&IOJ=^u*YY-^ls4w(h=d+jbc@`pApL*B^rJz)f`soQf@$P+&&|k|f-? zgA@rb?jGS2D(+qZtP^*isKE*kn*L2Y_ecc1Oz~*jrlNW4rcO!YhD=yMxIO5_9W;&a zlHM&49vD4f(+17r8EQ8nh`74;$Q3sFal9;0?9@&^T5Nx4v!5D z>EF`)piRW#3}b%erj?uB3PP6*skOu&zKdE6dFY!Edt(0!@82%@#0RophulLD8hHO?nsBfIO@km6Ps0j{4ePo) zcfz0!Nt&@V+!wo7g9#YYdiB^qUm~7~#$!72%Y=b!v?m6Wx?U{>Q%PxFXXo?BvH5m} z{tqlvQJ1CUWb3vSVRc=G(0%EVLm>TA41+yU4uy=V42KNcheXCy3py-O+9aF*UnM&I zc5D)i*E5IRGVQVjyghgj5=&)9n`&uBn=ZUk(<@)6Ib(`fX$I{x+6+`);W**ZE*G*T zXGJdjCgjG@Wyp>CJv3}A3&+T}pPV>3i^%z!WJH}r99<))hn#WLfrx97sKXub5RzRI z`yjADBy_9xm`Yl;Ph|z`lpmQC9H}tU<{@4RIdcUG92Bn# z62Qo}QRXP9dDRkqHkO}Wgt$diN9GRrq#$(9#4=b+S=^;}V(=^LMRL$EnLP0pODiKk z9nxu`ay(3>M}|IO?}c+8kG=AQK1fN#vX2a%D}H_y0Ls`ykLx*#B}mXR$b9PEk;fiD zj*(|S%Mx^W;oQj)Tby2~&JU~Y;<-1#LXSNBkYtL^oh(P__fck+i5_|R;;DyNCenXc zij>x&5%;oXE0^VJS@a5T-@1W<@}XlNT=@7IJ&*j%HRU{e#SME8OUQ|sXx+y&K+9ROc zu6n=?L0t99Ts9OY?jG`hhg=46oQ>e`p-WN%NQXWOfCPL>?z+kvowTO14v7}4ii;QP zZ{V4fJH&!L;6sWEAlr44&$ny_~`P(xaGfX~VhtSq7buFbmu1G!-h>N#=;H2!YZ z_}>cqIv3m1`34(>2U8ukc364?hr7Y&&9i%s^)% zPWpC&m}8i8j5C{Rj|QYNmP}R@^ZIg1C6%;UV*$|g^%XM~rF|%1eL(^EM^@t|?T)FE z8-KbeGnAFJ}_Rjb<h?%bksn%jmnXo@_EXNG6eC^qMkuYo=Upx5AL%sGTDJ{PJCF=gv&QFVjL$dYp}IgGgwAIMWj z=N3Fg!AdpkTR?F~;QSBlUYP(qK$1M__tXw`DaXeVRsKVB9P4p?6?CQH_B2df_5Eqc zuH#S^njKWdCaQuoGngIt*or?R0WfaeX_nCEB%ZGBh-=r5trPH-E!;_KtZf(ykzrf^ zx$87er)ZR^>om#)qybEsGoh7JfGWfeaeMy@Jd=`5n-=*CKotU|JQkqhJ=1UrK*h&; zS{kkp z2eG{?n2=i&5T<cM$m?;gv}N9cOUmaEApr5aa<(FJJ;P1==ZKY9xFXw1Mx%NpYU{KNY<8NTSEQY7dhW(+&UOc`R`?>|8I3pfNd%(=;Ks^rZpjM@9>_<@qC z5=MqvfCC7Ik&0)o<+fkPZ3t6r!9Umz`*YMVqz=RCTHlLjI1H)MpQAU^oy0kKzmX*~o`M7}L8i(Q7$C9gdrU$Ze#S*6fk^acQ3t~uT-)uf9kL_~*Lkkg z*y8bH_*7mtmc6i_8F}+l{dr`7urUr7(W%fKo1EnRrtv#XwRgK;FrTs zI?MRUnhJh`6^XAz*nBW`s2gVtK$FRsN&Zkbc81B(68d_>LTW_d3(%69uCIcYNb|2= z48nNaBsT#vAtRV?f(0xcHX)U3HWGZ52LwD*;xoQ14|w@_hyEz0f&LgdWspNZNx`+` zEF*{UjbZYgB4x2bMDEcdCU=<=!-(Qiwz8IO%2}W4#s))=AfC*qhxn^5M z)@WT4oZ$D)jhPahcpBB6q!(y`6F&93YMa`kQ+ym(`44#<>v3h4!nu6Y4Mvn6u8y-BC&ut} z$ugX+#%mDs3S!tq0_GF7qL${F&3po9S1~L0#a82W7>)XG!hB+!)wqV2_4Nt)WClSv zXRpz>G_3dThkQ>l@*C!g_PE*>`r9bj+d3jQXLLq-${muyN~gZ;CO(y&I+<~m47~ph z7^YVwchlQ-$F|OG8>Bfy{S}Jwwl@R&;NJbFzx+m|E^!++hRQc?e_(O_axB^n3jHt&@uEw7(P8=6(HMaH3yHWG9gpdpe8fmCt+I0}me==y`w2eG@BMP3~GCPi_WWV`gAkgzR9_5vM_gD-=SAA-9jwv*)n zSqG4L_6IP}CMp8sY!Y-y94`1_xxjTnJb>vpgy+SuY4F1~@&Afh)_t~hpF?;3Utp>o zNG%rEPzcrqWS3C#T_=6|JQ!>TQf?|cwNYGerQamxS?L?CGUi(;_rRh-mT`|*Xyxgt zlz~s7onnzCoPTG6aPGxh8M*(>(W9SMiRCO1!`yoGk#{e`f`D=rS?$jPt6beOO+SP* z{b%I74u`W|eE1`jDaGh#KP#Rb9(($8GQ%d>ZKNc>>o3qVZT;9VR!C2KnQ^ytIy z+hp=xTQ}-&QtlRVi1&)Pm$$ENCwC3ItJz&8Ee;~?4vy|(HpZwV@1S-7WH_bA&G+wTr z|8nHsUtn6>L|#>{>B&Ui^^}tryCC1VRouWLseKs@(ekAgK9#r&9kS90b$y70+y(YW z?NY8izPvKsC>6ZBT$y2bz6mjR_1Y=KT>eIn#oX&Ah`FWamSxmW z?!Tvjq+J>VNy>MUa%Yt4*;JMkaZV@c;C--y}U<$=up(~^e9B#Z>!*5 z?vbQC)xDB&m7d9PrFSxH^-u<`s^jI^E%<7^qI@rb5tW#hicpX5ty!359()T{x;&j` z3Hdt7*-XwYa7>&!W6eJ^RQ;yRK;f8qEX&KKjMOQXwU=E9p~Bz`UF9KRDgp-Bn+URFMn9z z)Bgr=0K|I!-uiC{4nQf*q=_f{Y8)2nrNjGSAc;drtUD8G!$&_N0QrPIVVG?R+H)oq zv|;WKbNeivhS0I1y}hkt)v8tD#l=%Ek3IPrw8RjNq1SHF&m!Hf80IemvSg%3AKesB zJ`H!0$KESH_S!R}Z~hoUc=59b#>w2jq&y^scXsZ&@bRlqO6%{JqDJn=DbF9_;{!hE zVa?W!6YF4%0O#3Dtl<4&mf>@5*#B>p_A`4?nCaY_n_E7?(su4;i3qU-ufL0|FsAIo zZQKU{`Z0=2l0$5a{vsUYoJaoSi9H=N*V0t6 z?LTB~{^ttfE{|9Y5;uhSM*bE6=8A0TU$rhKmRsiEiJPSr!mHyy!ZRsrbj6Z2Tl#M) zOV{hhYpMyR${3ivbh<8`iLZjSyzdKi)zy~$e!~IFem;c|tFjSaotA9;aSkucf&)-n z)MRf!cP5^9Gji_O$gh4HmZlA1c@)UypLR3FCjpi30BlO`2@-tl7ubHTGE=$BX`x+U-~AyYIL{^ZPaJWgtMi_vVge?a^f`SFTyOa&tMF z&HCluO{qox{)fnFmqsHs*3|k!n|#)MYc$4WJqD@NMTfw!L4HHk=v`9n zO|wGhMob9`yn`&iaiK2Wv7KrS)ZW*tZ92urah3nR4p^W824=frA`yd`^dAK_Kqoy< zjt$J2(3L3w0zwveD*tDACZ&Rx2M|<@_Upcc(f)%I;DKkp)$o8m4jv#oX5E@OUk6Cg z#|PI}4m~K99i`JnE#;A+n!WP}KvOT-NH_dm@vr+TWM059|Uz_$UWU z{W!esas_^`d?WlZu32048l+-u8x?vhIk%BRxbh!ZZ~sSiqCkQ6+%62#M3ue!3sv@) zkm;|TxMNQ$*w>(DFD~A+uS8!z7>2Ih4I!G;eQrw>=c8{)h_)Gz`wDK$c$~y$)e`Y> zI1p>~VRSDK%q@5Z$pjr=BqA4d`Y6FVULArB$5^EhfWW5{;MjQBT|wkIkAv8}IAtJ& zkPio_g&-*52Yf^w4D;_}zyUw;B4Gd+;Wy$4IG<=Js7H3?eVvYdw-)^PK@&I3^l|t& z4&G@x=z@N~38wKlAf3(gDcyrluyLmY+mN~hN4EJ1!N#GvWH&H_?uY&!N=_C1Y2v3; zo1GY1!$5*h0t;48$i{$ALV%!!A0_F;Yp8%?ECN|)2-G2Ed8ADg_X)YubvQU+8yx$9P2itY^KLr( zBEdL*T?))S(<$Cw@Z%1Aa1S409l()-)(2;%n~txRChzm9CUzE3bvO{E`aA%Ouzo-* zkMT6?L;(8k*0Nd$GC+2#bVhCnetGs6_{{qW#ZbK zq77v+;3|SZKQs7;LJ;!f5QMAz7S7Mh&>;hV7=G)Uzy$uBR{aO$oFZpGoYIFfUj+$} zX79EIO^29YIUL|-IAETw9J^6~ExNoTpqj4=4E*p)fq{-P0svrOIjpCmYgeym?^w8c z6aJHTx%4h;U)8a4h0VWm0(vmkg!Yg5;N<2{Ko8L0@UD`4LnkPdKkEN?c%TYHsIZuq zMiFKJNSTNt(3wi5%B(@ZB$V*y)C_LRlu*JsWI050p$sLgRhO%+I>pnOj#Ni93KC|M z+UJ04BEYJ^gIs3DTBz{RMV+Pj`3`WbLSI-k3v{|WVPB{}qsLu57`&5}xF`{~!f`carx z`ZeGTiKY&ncmVz#sL1u@tmWVKZI!=T+G_o3sr)HZwUm#4t5m0n5K%ifZc3+m61{qu z$|L0jpN7C+9k6Kz12H^=((Ho_Ya{ZrUjB_<28$w%wgJTPe)QwLk*2C~EXCGZ2$Yp+ zn*C*1d2ITF3eTY4BoE^J9<@6YfrEoG9gTF11O0=Mp7jq$2&rzjEA%4={o7psBS#yq U#kl6+T7YZ0WEbQSLX)}w4{d->NB{r; literal 0 HcmV?d00001 diff --git a/src/backend/JDSpiders/Spider/__pycache__/dataCleaning.cpython-37.pyc b/src/backend/JDSpiders/Spider/__pycache__/dataCleaning.cpython-37.pyc new file mode 100644 index 0000000000000000000000000000000000000000..0ff869f458b709f22d1dd440729cfd57f7bf42dc GIT binary patch literal 21251 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

HJVTm{9_xz zp-B7L0lQh=Nq~S_3{WsB#UL1yw+}vzp(%GOVt)beR(#sDso_~{>U?(*lo^xS*tm$b zvk`F~Y*XdV#zxrGX#N_!&pB=CM!?d#5Zn;fx?u`j-yXVV&gxJzbz1Zl6w(Z8l zE^f#{Zku{n?)j@BJ;?jExJnD#9y7a5|5rSA-ZmXu{&?N&-9*1mLqTY?xbU*o_7L1B zo zb@Zikr_aa$`*=MzU+0IDTDrhL8dUIot7}dC+t+Brcq4^yPc}x39Z>jSmi3Mq{zbNH z`uXQ3PyBfDk)NMC`XKvnc-@VkCdl3cH_B%;g{usYF9e2=zf!=pBF2ZDB-9$4sspwFcE}Clr`FWL!8HHc8UTmg z%KlYD+AF_Rz@3m5zv4fs?u@)TONZtQ9lj_h%J)b~S5|85M5&jHw95Mb7AmxplFAOp z*?iv%@~FtrcY+W6(*ju9S-=8DqSmK^a&C{$=24mT z2L^1(hHS}W2SzxeOdS!JcmXJoiE4-yK=V%tb|P-#$ZP-4p0mF3EM zoZX~!D!Y(wSN>MHR=Hf+pj^iH;D=-UiG;|e5(yb9eLX6PE8SbRW;26`gy21|RQYUA XHIz;A4ctf#;a^E4W2|6