fix: 修复无附件文章无法标记已读的问题
- 发现标记已读的正确 API: /tools/submit_ajax.ashx?action=saveread - 添加 mark_article_read 方法调用 saveread API 标记文章已读 - 修改 get_article_attachments 返回文章的 channel_id 和 article_id - 对每篇文章都调用 mark_article_read,无论是否有附件 - 解决米米88、黄紫夏99等账号文章无法标记已读的问题 Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -351,7 +351,14 @@ class APIBrowser:
|
|||||||
return articles, total_pages, next_page_url
|
return articles, total_pages, next_page_url
|
||||||
|
|
||||||
def get_article_attachments(self, article_href: str):
|
def get_article_attachments(self, article_href: str):
|
||||||
"""获取文章的附件列表"""
|
"""
|
||||||
|
获取文章的附件列表和文章信息
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
tuple: (attachments_list, article_info)
|
||||||
|
- attachments_list: 附件列表
|
||||||
|
- article_info: 包含 channel_id 和 article_id 的字典,用于标记文章已读
|
||||||
|
"""
|
||||||
if not article_href.startswith('http'):
|
if not article_href.startswith('http'):
|
||||||
url = f"{BASE_URL}/admin/{article_href}"
|
url = f"{BASE_URL}/admin/{article_href}"
|
||||||
else:
|
else:
|
||||||
@@ -361,6 +368,16 @@ class APIBrowser:
|
|||||||
soup = BeautifulSoup(resp.text, 'html.parser')
|
soup = BeautifulSoup(resp.text, 'html.parser')
|
||||||
|
|
||||||
attachments = []
|
attachments = []
|
||||||
|
article_info = {'channel_id': None, 'article_id': None}
|
||||||
|
|
||||||
|
# 从 saveread 按钮获取 channel_id 和 article_id
|
||||||
|
for elem in soup.find_all(['button', 'input']):
|
||||||
|
onclick = elem.get('onclick', '')
|
||||||
|
match = re.search(r'saveread\((\d+),(\d+)\)', onclick)
|
||||||
|
if match:
|
||||||
|
article_info['channel_id'] = match.group(1)
|
||||||
|
article_info['article_id'] = match.group(2)
|
||||||
|
break
|
||||||
|
|
||||||
attach_list = soup.find('div', {'class': 'attach-list2'})
|
attach_list = soup.find('div', {'class': 'attach-list2'})
|
||||||
if attach_list:
|
if attach_list:
|
||||||
@@ -383,10 +400,31 @@ class APIBrowser:
|
|||||||
})
|
})
|
||||||
break
|
break
|
||||||
|
|
||||||
return attachments
|
return attachments, article_info
|
||||||
|
|
||||||
|
def mark_article_read(self, channel_id: str, article_id: str) -> bool:
|
||||||
|
"""通过 saveread API 标记文章已读"""
|
||||||
|
if not channel_id or not article_id:
|
||||||
|
return False
|
||||||
|
|
||||||
|
import random
|
||||||
|
saveread_url = f"{BASE_URL}/tools/submit_ajax.ashx?action=saveread&time={random.random()}&fl={channel_id}&id={article_id}"
|
||||||
|
|
||||||
|
try:
|
||||||
|
resp = self._request_with_retry("post", saveread_url)
|
||||||
|
# 检查响应是否成功
|
||||||
|
if resp.status_code == 200:
|
||||||
|
try:
|
||||||
|
data = resp.json()
|
||||||
|
return data.get('status') == 1
|
||||||
|
except:
|
||||||
|
return True # 如果不是 JSON 但状态码 200,也认为成功
|
||||||
|
return False
|
||||||
|
except:
|
||||||
|
return False
|
||||||
|
|
||||||
def mark_read(self, attach_id: str, channel_id: str = '1') -> bool:
|
def mark_read(self, attach_id: str, channel_id: str = '1') -> bool:
|
||||||
"""通过访问预览通道标记已读"""
|
"""通过访问预览通道标记附件已读"""
|
||||||
download_url = f"{BASE_URL}/tools/download2.ashx?site=main&id={attach_id}&channel_id={channel_id}"
|
download_url = f"{BASE_URL}/tools/download2.ashx?site=main&id={attach_id}&channel_id={channel_id}"
|
||||||
|
|
||||||
try:
|
try:
|
||||||
@@ -499,9 +537,9 @@ class APIBrowser:
|
|||||||
new_articles_in_page += 1
|
new_articles_in_page += 1
|
||||||
title = article['title'][:30]
|
title = article['title'][:30]
|
||||||
|
|
||||||
# 获取附件(文章详情页)
|
# 获取附件和文章信息(文章详情页)
|
||||||
try:
|
try:
|
||||||
attachments = self.get_article_attachments(article_href)
|
attachments, article_info = self.get_article_attachments(article_href)
|
||||||
consecutive_failures = 0
|
consecutive_failures = 0
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
skipped_items += 1
|
skipped_items += 1
|
||||||
@@ -516,12 +554,25 @@ class APIBrowser:
|
|||||||
total_items += 1
|
total_items += 1
|
||||||
report_progress()
|
report_progress()
|
||||||
|
|
||||||
|
# 标记文章已读(调用 saveread API)
|
||||||
|
article_marked = False
|
||||||
|
if article_info.get('channel_id') and article_info.get('article_id'):
|
||||||
|
article_marked = self.mark_article_read(
|
||||||
|
article_info['channel_id'],
|
||||||
|
article_info['article_id']
|
||||||
|
)
|
||||||
|
|
||||||
|
# 处理附件(如果有)
|
||||||
if attachments:
|
if attachments:
|
||||||
for attach in attachments:
|
for attach in attachments:
|
||||||
if self.mark_read(attach['id'], attach['channel_id']):
|
if self.mark_read(attach['id'], attach['channel_id']):
|
||||||
total_attachments += 1
|
total_attachments += 1
|
||||||
|
|
||||||
self.log(f"[API] [{total_items}] {title} - {len(attachments)}个附件")
|
self.log(f"[API] [{total_items}] {title} - {len(attachments)}个附件")
|
||||||
|
else:
|
||||||
|
# 没有附件的文章,只记录标记状态
|
||||||
|
status = "已标记" if article_marked else "标记失败"
|
||||||
|
self.log(f"[API] [{total_items}] {title} - 无附件({status})")
|
||||||
|
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user