collection_img.py 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152
  1. # -*- coding: utf-8 -*-
  2. import time
  3. import os
  4. import zipfile
  5. import httpx
  6. from odoo import models, fields, api
  7. from odoo.exceptions import UserError
  8. class CollectionImg(models.Model):
  9. _name = 'collection.img'
  10. _description = 'Collection Img'
  11. _order = 'create_date DESC'
  12. line_ids = fields.One2many('collection.img.line', 'collection_img_id', string='Img Lines')
  13. name = fields.Char(string='Name', default=str(int(time.time())))
  14. target_site_id = fields.Many2one('collection.img.target.site', string='Target Base Site')
  15. file_title = fields.Char(string='File Title')
  16. img_set_url = fields.Char(string='Image Set URL')
  17. show_browser = fields.Boolean(string='Show Browser', default=False)
  18. image_count = fields.Integer(string='Image Count')
  19. def btn_get_img_data(self):
  20. # 删除之前保存的 line
  21. self.btn_clear_data()
  22. if self.target_site_id.name not in self.img_set_url:
  23. raise UserError('target web site incorrect')
  24. self._check_file_exist()
  25. try:
  26. exec(self.target_site_id.codes)
  27. except Exception as e:
  28. raise UserError(str(e))
  29. def btn_download_img(self):
  30. self._check_file_exist()
  31. # 检查一下 line 有没有缺少 url
  32. for line in self.line_ids:
  33. if not line.url:
  34. raise UserError(f'{line.name}{line.serial} Missing image address')
  35. # 先查看下载位置的文件夹, 有没有这个图片合集的文件夹
  36. download_path = os.path.join('/tmp/collection_downloads', self.target_site_id.name, self.file_title)
  37. if not os.path.exists(download_path):
  38. os.mkdir(download_path)
  39. # 准备一个列表存放图片路径, 然后打包下载
  40. img_path_list = []
  41. # 一行一行处理数据, 以后或者成使用多线程或者对进程或协程
  42. for line in self.line_ids:
  43. if line.set_name:
  44. # 这里是有分图片合集的情况, 即类似 comico
  45. pass
  46. else:
  47. # 这里是没有分图片合集的情况, 即类似 图片资源站
  48. img_file_path = os.path.join(download_path, line.name + '.' + line.image_suffix)
  49. if os.path.exists(img_file_path): # 这个图片存在就直接加入打包列表, 否则就下载
  50. img_path_list.append(img_file_path)
  51. line.update({'download_state': 'downloaded'})
  52. continue
  53. # 这里开始下载图片
  54. retry_count = 10
  55. while retry_count:
  56. try:
  57. img = httpx.get(line.url, headers={
  58. "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/130.0.0.0 Safari/537.36"
  59. })
  60. if img.status_code == 200:
  61. with open(img_file_path, 'wb') as f:
  62. f.write(img.content)
  63. line.update({'download_state': 'downloaded'})
  64. img_path_list.append(img_file_path)
  65. break
  66. else:
  67. time.sleep(5)
  68. retry_count -= 1
  69. except Exception as e:
  70. print(str(e))
  71. time.sleep(5)
  72. retry_count -= 1
  73. # 打这里所有的 img 都已经下载完, 并且所有图片路径已经存入 img_path_list 中
  74. # 这里开始打包下载好的图片
  75. zip_file_path = os.path.join(download_path, self.file_title + '.zip')
  76. with zipfile.ZipFile(zip_file_path, 'w') as zip_file:
  77. for img_path in img_path_list:
  78. zip_file.write(img_path, os.path.basename(img_path))
  79. # 构建下载地址
  80. download_url = f"{download_path}.zip"
  81. print(download_url)
  82. # 返回一个动作字典,用于下载文件
  83. return {
  84. 'type': 'ir.actions.act_url',
  85. "url": download_url
  86. }
  87. def btn_clear_data(self):
  88. for line in self.line_ids:
  89. line.unlink()
  90. def _check_file_exist(self):
  91. # 如果下载位置的文件夹不存在, 则创建一个先
  92. download_path = '/tmp/collection_downloads'
  93. if not os.path.exists(download_path):
  94. os.mkdir(download_path)
  95. # 然后查看对应网站的储存文件夹在不在,不在就创建一个
  96. target_site_name = os.path.join(download_path, self.target_site_id.name)
  97. if not os.path.exists(target_site_name):
  98. os.mkdir(target_site_name)
  99. class CollectionImgLine(models.Model):
  100. _name = 'collection.img.line'
  101. _description = 'Collection Img Line'
  102. collection_img_id = fields.Many2one('collection.img', string='Collection Img', ondelete='cascade')
  103. name = fields.Char(string='Name')
  104. set_name = fields.Char(string='Set Name')
  105. serial = fields.Integer(string='Serial')
  106. url = fields.Char(string='URL')
  107. download_state = fields.Selection([('not_download', 'not download'), ('downloaded', 'downloaded')],
  108. string='Download State', default='not_download')
  109. image_suffix = fields.Char(string='Image Suffix')
  110. class CollectionImgTargetSite(models.Model):
  111. _name = 'collection.img.target.site'
  112. _description = 'Collection Img Target Site'
  113. name = fields.Char(string='Name')
  114. target_url = fields.Char(string='Target URL')
  115. codes = fields.Text(string='Codes')