Browse Source

添加请求失败自动重试

huangyan 10 months ago
parent
commit
f511436d2b
4 changed files with 173 additions and 91 deletions
  1. 65 0
      logs/scrapy.log
  2. BIN
      nmc/spiders/__pycache__/nmcspider.cpython-311.pyc
  3. 108 91
      nmc/spiders/nmcspider.py
  4. BIN
      screenshot.png

+ 65 - 0
logs/scrapy.log

@@ -0,0 +1,65 @@
+2024-06-05 13:53:06 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ANM/kangbashitiyuzhongxin.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 13:59:23 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AJL/fusong.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:06:26 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/zuojiang.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:07:01 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/yuhang.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:07:33 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/xiangshan.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:08:27 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/qiantang.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:08:54 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/pingyang.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:09:16 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/nanzuo.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:09:38 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/luqiao.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:10:04 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/longgang.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:10:37 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/jiangbei.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:11:04 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/huangyan.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:11:26 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/huzhou.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:11:50 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/haishu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:12:21 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/deqing.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:12:52 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/cangnan.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:13:34 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AZJ/shaoxing.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:19:48 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AFJ/diaoyudao.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:21:15 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AJX/sanqingshan.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:22:36 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AJX/gongqingcheng.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:34:20 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AHB/suixian.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:35:59 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AHB/yichang.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:37:19 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AHN/yueyangxian.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:40:23 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AHN/wangchengqu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:41:20 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGD/yangshan.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:42:56 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGD/huilai.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:45:46 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGX/rongshui.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:46:09 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGX/rongan.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:47:01 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGX/luzhai.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:47:33 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGX/liuzhou.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:47:55 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGX/liujiang.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:48:18 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGX/liucheng.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:49:51 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGX/cangwu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:50:31 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGX/nanningchengqu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:51:33 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AHI/sanya.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:52:06 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AHI/huangyandao.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:53:21 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ACQ/nanchuan.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:54:21 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/zuozhou.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:55:12 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/yibin.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:55:35 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/yilongxinzheng.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:57:21 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/qianfeng.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:59:22 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/huilichengqu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 14:59:47 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/huazuo.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:00:39 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/deyang.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:01:16 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/daying.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:01:51 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/baoxing.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:03:09 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASC/chengdu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:04:57 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGZ/panzhou.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:06:30 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGZ/anshun.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:15:43 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASN/weinan.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:18:31 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ASN/xian.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:19:07 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGS/zhangye.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:19:52 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGS/wuwei.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:20:23 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGS/tianzhu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:23:34 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AGS/jiayuguan.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:25:15 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AQH/chengduochalagou.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:28:15 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AXJ/moyu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:28:55 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AXJ/kuerle.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:29:21 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AXJ/kashi.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:29:49 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AXJ/huoerguosi.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:30:37 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AXJ/changji.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:31:09 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AXJ/bohu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:31:49 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AXJ/akesu.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:32:37 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/AXJ/atushi.html 上,在指定时间内未能找到指定元素使用默认图片
+2024-06-05 15:33:06 [nmcspider] ERROR: 在页面 http://www.nmc.cn/publish/forecast/ATW/gaoxiong.html 上,在指定时间内未能找到指定元素使用默认图片

BIN
nmc/spiders/__pycache__/nmcspider.cpython-311.pyc


+ 108 - 91
nmc/spiders/nmcspider.py

@@ -22,6 +22,19 @@ def js_is_complete(driver):
     return driver.execute_script("return document.readyState") == "complete"
 
 
+def retry_get_url(driver, url, retries=3, delay=5):
+    for attempt in range(retries):
+        try:
+            driver.get(url)
+            # 可以在这里添加额外的检查,确认页面是否成功加载
+            return True  # 成功访问URL,退出循环
+        except TimeoutException:
+            if attempt < retries - 1:  # 如果还没达到最大重试次数
+                time.sleep(delay)  # 等待一段时间后重试
+            else:
+                return False  # 所有重试都失败了
+
+
 class NmcspiderSpider(scrapy.Spider):
     name = "nmcspider"
     allowed_domains = ["www.nmc.cn"]
@@ -71,110 +84,114 @@ class NmcspiderSpider(scrapy.Spider):
         province = response.meta['province']
         # 城市名称
         city = response.meta['city']
-        self.driver.get(response.url)
-        self.driver.set_window_size(1920, 1080)
-        # 创建文件目录
-        today_str = datetime.now().strftime("%Y-%m-%d")
-        path_to_save = os.path.join("resource", province, city, today_str)
-        full_path = os.path.join(".", path_to_save)
-        if not os.path.exists(full_path):
-            os.makedirs(full_path)
-        # 获取第一张图片-天气预报
-        element = WebDriverWait(self.driver, 20).until(
-            EC.presence_of_element_located((By.XPATH, '/html/body/div[2]/div')))
-        self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", element)
-        location = element.location
-        size = element.size
-        # 获取天气预报图
-        # 使用PIL和numpy处理图像
-        screenshot = self.driver.get_screenshot_as_png()
-        image = Image.open(io.BytesIO(screenshot))
-        crop_area = (location['x'], location['y'], location['x'] + size['width'], location['y'] + size['height'])
-        cropped_image = image.crop(crop_area)
-        # 将图像转换为RGB模式,因为JPEG格式需要此模式
-        cropped_image = cropped_image.convert("RGB")
-        # 保存裁剪后的图片
-        url = urlparse(response.url)
-        parts = url.path.split('/')
-        target_part = '_'.join([parts[3], parts[4].split('.')[0]])
-        name = target_part + "_1.png"
-        jpeg_name = name.rsplit('.', 1)[0] + ".jpg"
-        jpeg_path = os.path.join(full_path, jpeg_name)
-        quality = 50
-        # image_path = os.path.join(full_path, name)
-        cropped_image.save(jpeg_path, "JPEG", quality=quality)
-        # 获取第二张图片
-        highcharts = WebDriverWait(self.driver, 20).until(
-            EC.presence_of_element_located((By.ID, 'realChart')))
-        self.driver.execute_script("arguments[0].scrollIntoView({block: 'center', behavior: 'instant'});",
-                                   highcharts)
-        # time.sleep(2)
-        # 获取屏幕截图
-        screenshot = self.driver.get_screenshot_as_png()
-        script = """
-                var element = document.getElementById('realChart');
-                var rect = element.getBoundingClientRect();
-                return {left: rect.left, top: rect.top, width: rect.width, height: rect.height};
-                """
-        position_info = self.driver.execute_script(script)
-        # 获取天气预报图
-        # 使用PIL和numpy处理图像
-        image = Image.open(io.BytesIO(screenshot))
-        crop_area = (
-            position_info['left'], position_info['top'],
-            position_info['left'] + position_info['width'],
-            position_info['top'] + position_info['height'])
-        cropped_image = image.crop(crop_area)
-        # 保存裁剪后的图片
-        name = target_part + "_2.png"
-        image_path = os.path.join(full_path, name)
-        cropped_image.save(image_path)
-        try:
-            # 第三张图片
-            # 等待js全部加载完成
-            js_is_complete(self.driver)
-            WebDriverWait(self.driver, 20).until(js_is_complete)
+        success = retry_get_url(self.driver, response.url)
+        if success == False:
+            self.logger.error(f"{response.url}超过最大重试次数")
+        else:
+            # self.driver.get(response.url)
+            self.driver.set_window_size(1920, 1080)
+            # 创建文件目录
+            today_str = datetime.now().strftime("%Y-%m-%d")
+            path_to_save = os.path.join("resource", province, city, today_str)
+            full_path = os.path.join(".", path_to_save)
+            if not os.path.exists(full_path):
+                os.makedirs(full_path)
+            # 获取第一张图片-天气预报
+            element = WebDriverWait(self.driver, 20).until(
+                EC.presence_of_element_located((By.XPATH, '/html/body/div[2]/div')))
+            self.driver.execute_script("arguments[0].scrollIntoView({block: 'center'});", element)
+            location = element.location
+            size = element.size
+            # 获取天气预报图
+            # 使用PIL和numpy处理图像
+            screenshot = self.driver.get_screenshot_as_png()
+            image = Image.open(io.BytesIO(screenshot))
+            crop_area = (location['x'], location['y'], location['x'] + size['width'], location['y'] + size['height'])
+            cropped_image = image.crop(crop_area)
+            # 将图像转换为RGB模式,因为JPEG格式需要此模式
+            cropped_image = cropped_image.convert("RGB")
+            # 保存裁剪后的图片
+            url = urlparse(response.url)
+            parts = url.path.split('/')
+            target_part = '_'.join([parts[3], parts[4].split('.')[0]])
+            name = target_part + "_1.png"
+            jpeg_name = name.rsplit('.', 1)[0] + ".jpg"
+            jpeg_path = os.path.join(full_path, jpeg_name)
+            quality = 50
+            # image_path = os.path.join(full_path, name)
+            cropped_image.save(jpeg_path, "JPEG", quality=quality)
+            # 获取第二张图片
             highcharts = WebDriverWait(self.driver, 20).until(
-                EC.presence_of_element_located((By.CSS_SELECTOR, '#container')))
+                EC.presence_of_element_located((By.ID, 'realChart')))
             self.driver.execute_script("arguments[0].scrollIntoView({block: 'center', behavior: 'instant'});",
                                        highcharts)
-            # 找到点击的按钮
-            WebDriverWait(self.driver, 20).until(
-                EC.presence_of_element_located((By.CSS_SELECTOR,
-                                                '#container> .highcharts-container >svg > g > g > g >g.highcharts-legend-item.highcharts-column-series.highcharts-color-undefined.highcharts-series-0')))
-            element = self.driver.find_element(By.CSS_SELECTOR,
-                                               '#container> .highcharts-container >svg > g > g > g >g.highcharts-legend-item.highcharts-column-series.highcharts-color-undefined.highcharts-series-0')
-            self.driver.execute_script("arguments[0].dispatchEvent(new Event('click'));",
-                                       element)
-            # 等待点击之后页面加载完成
-            WebDriverWait(self.driver, 20).until(EC.visibility_of_element_located((By.ID, 'container')))
             # time.sleep(2)
             # 获取屏幕截图
             screenshot = self.driver.get_screenshot_as_png()
-            scripts = """
-                        var element = document.getElementById('container');
-                        var rect = element.getBoundingClientRect();
-                        return {left: rect.left, top: rect.top, width: rect.width, height: rect.height};
-                        """
-            position_info = self.driver.execute_script(scripts)
+            script = """
+                    var element = document.getElementById('realChart');
+                    var rect = element.getBoundingClientRect();
+                    return {left: rect.left, top: rect.top, width: rect.width, height: rect.height};
+                    """
+            position_info = self.driver.execute_script(script)
             # 获取天气预报图
             # 使用PIL和numpy处理图像
             image = Image.open(io.BytesIO(screenshot))
             crop_area = (
-                position_info['left'], position_info['top'] + 50,
+                position_info['left'], position_info['top'],
                 position_info['left'] + position_info['width'],
                 position_info['top'] + position_info['height'])
             cropped_image = image.crop(crop_area)
             # 保存裁剪后的图片
-            name = target_part + "_3.png"
+            name = target_part + "_2.png"
             image_path = os.path.join(full_path, name)
             cropped_image.save(image_path)
-        except TimeoutException:
-            default_image_path = "/default_image.png"  # 这里填写默认图片的路径
-            backup_image = Image.open(default_image_path)
-            name = target_part + "_3.png"
-            image_path = os.path.join(full_path, name)
-            backup_image.save(image_path)
-            current_url = self.driver.current_url  # 获取当前页面的URL
-            self.logger.error(
-                f"在页面 {current_url} 上,在指定时间内未能找到指定元素使用默认图片")
+            try:
+                # 第三张图片
+                # 等待js全部加载完成
+                js_is_complete(self.driver)
+                WebDriverWait(self.driver, 20).until(js_is_complete)
+                highcharts = WebDriverWait(self.driver, 20).until(
+                    EC.presence_of_element_located((By.CSS_SELECTOR, '#container')))
+                self.driver.execute_script("arguments[0].scrollIntoView({block: 'center', behavior: 'instant'});",
+                                           highcharts)
+                # 找到点击的按钮
+                WebDriverWait(self.driver, 20).until(
+                    EC.presence_of_element_located((By.CSS_SELECTOR,
+                                                    '#container> .highcharts-container >svg > g > g > g >g.highcharts-legend-item.highcharts-column-series.highcharts-color-undefined.highcharts-series-0')))
+                element = self.driver.find_element(By.CSS_SELECTOR,
+                                                   '#container> .highcharts-container >svg > g > g > g >g.highcharts-legend-item.highcharts-column-series.highcharts-color-undefined.highcharts-series-0')
+                self.driver.execute_script("arguments[0].dispatchEvent(new Event('click'));",
+                                           element)
+                # 等待点击之后页面加载完成
+                WebDriverWait(self.driver, 20).until(EC.visibility_of_element_located((By.ID, 'container')))
+                # time.sleep(2)
+                # 获取屏幕截图
+                screenshot = self.driver.get_screenshot_as_png()
+                scripts = """
+                            var element = document.getElementById('container');
+                            var rect = element.getBoundingClientRect();
+                            return {left: rect.left, top: rect.top, width: rect.width, height: rect.height};
+                            """
+                position_info = self.driver.execute_script(scripts)
+                # 获取天气预报图
+                # 使用PIL和numpy处理图像
+                image = Image.open(io.BytesIO(screenshot))
+                crop_area = (
+                    position_info['left'], position_info['top'] + 50,
+                    position_info['left'] + position_info['width'],
+                    position_info['top'] + position_info['height'])
+                cropped_image = image.crop(crop_area)
+                # 保存裁剪后的图片
+                name = target_part + "_3.png"
+                image_path = os.path.join(full_path, name)
+                cropped_image.save(image_path)
+            except TimeoutException:
+                default_image_path = r"E:\pySpider\nmc\default_image.png"  # 这里填写默认图片的路径
+                backup_image = Image.open(default_image_path)
+                name = target_part + "_3.png"
+                image_path = os.path.join(full_path, name)
+                backup_image.save(image_path)
+                current_url = self.driver.current_url  # 获取当前页面的URL
+                self.logger.error(
+                    f"在页面 {current_url} 上,在指定时间内未能找到指定元素使用默认图片")

BIN
screenshot.png