| 28 | from tools.words import AsyncWordCloudGenerator |
| 29 | |
| 30 | class AsyncFileWriter: |
| 31 | def __init__(self, platform: str, crawler_type: str): |
| 32 | self.lock = asyncio.Lock() |
| 33 | self.platform = platform |
| 34 | self.crawler_type = crawler_type |
| 35 | self.wordcloud_generator = AsyncWordCloudGenerator() if config.ENABLE_GET_WORDCLOUD else None |
| 36 | |
| 37 | def _get_file_path(self, file_type: str, item_type: str) -> str: |
| 38 | if config.SAVE_DATA_PATH: |
| 39 | base_path = f"{config.SAVE_DATA_PATH}/{self.platform}/{file_type}" |
| 40 | else: |
| 41 | base_path = f"data/{self.platform}/{file_type}" |
| 42 | pathlib.Path(base_path).mkdir(parents=True, exist_ok=True) |
| 43 | file_name = f"{self.crawler_type}_{item_type}_{utils.get_current_date()}.{file_type}" |
| 44 | return f"{base_path}/{file_name}" |
| 45 | |
| 46 | async def write_to_csv(self, item: Dict, item_type: str): |
| 47 | file_path = self._get_file_path('csv', item_type) |
| 48 | async with self.lock: |
| 49 | file_exists = os.path.exists(file_path) |
| 50 | async with aiofiles.open(file_path, 'a', newline='', encoding='utf-8-sig') as f: |
| 51 | writer = csv.DictWriter(f, fieldnames=item.keys()) |
| 52 | if not file_exists or await f.tell() == 0: |
| 53 | await writer.writeheader() |
| 54 | await writer.writerow(item) |
| 55 | |
| 56 | async def write_to_jsonl(self, item: Dict, item_type: str): |
| 57 | file_path = self._get_file_path('jsonl', item_type) |
| 58 | async with self.lock: |
| 59 | async with aiofiles.open(file_path, 'a', encoding='utf-8') as f: |
| 60 | await f.write(json.dumps(item, ensure_ascii=False) + '\n') |
| 61 | |
| 62 | async def write_single_item_to_json(self, item: Dict, item_type: str): |
| 63 | file_path = self._get_file_path('json', item_type) |
| 64 | async with self.lock: |
| 65 | existing_data = [] |
| 66 | if os.path.exists(file_path) and os.path.getsize(file_path) > 0: |
| 67 | async with aiofiles.open(file_path, 'r', encoding='utf-8') as f: |
| 68 | try: |
| 69 | content = await f.read() |
| 70 | if content: |
| 71 | existing_data = json.loads(content) |
| 72 | if not isinstance(existing_data, list): |
| 73 | existing_data = [existing_data] |
| 74 | except json.JSONDecodeError: |
| 75 | existing_data = [] |
| 76 | |
| 77 | existing_data.append(item) |
| 78 | |
| 79 | async with aiofiles.open(file_path, 'w', encoding='utf-8') as f: |
| 80 | await f.write(json.dumps(existing_data, ensure_ascii=False, indent=4)) |
| 81 | |
| 82 | async def generate_wordcloud_from_comments(self): |
| 83 | """ |
| 84 | Generate wordcloud from comments data |
| 85 | Only works when ENABLE_GET_WORDCLOUD and ENABLE_GET_COMMENTS are True |
| 86 | """ |
| 87 | if not config.ENABLE_GET_WORDCLOUD or not config.ENABLE_GET_COMMENTS: |
no outgoing calls
no test coverage detected