318 lines
13 KiB
Python
Executable File
318 lines
13 KiB
Python
Executable File
#!/usr/bin/env python3
|
|
# -*- coding: utf-8 -*-
|
|
"""
|
|
get_Plant_mPLoc_out.py
|
|
自动化从Plant-mPLoc网站获取蛋白质亚细胞定位预测结果
|
|
使用方法: python get_Plant_mPLoc_out.py --input <fasta文件> --output <结果文件>
|
|
"""
|
|
|
|
import argparse
|
|
import time
|
|
import shutil
|
|
import sys
|
|
from selenium import webdriver
|
|
from selenium.webdriver.common.by import By
|
|
from selenium.webdriver.common.alert import Alert
|
|
from selenium.webdriver.firefox.options import Options
|
|
from selenium.webdriver.firefox.service import Service
|
|
from selenium.webdriver.support.ui import WebDriverWait
|
|
from selenium.webdriver.support import expected_conditions as EC
|
|
from lxml import etree
|
|
|
|
|
|
def get_Plant_mPLoc_out(arg1, arg2):
|
|
"""使用Selenium自动从Plant-mPLoc网站获取亚细胞定位预测结果"""
|
|
|
|
# 1. 读取FASTA文件
|
|
fa_dict = {}
|
|
with open(arg1, "rt") as fr:
|
|
current_id = ""
|
|
for line in fr:
|
|
line = line.strip()
|
|
if not line:
|
|
continue
|
|
|
|
if line.startswith(">"):
|
|
# 提取ID(取">"后的部分,并按"."分割取第一部分)
|
|
current_id = line[1:].split(".")[0]
|
|
fa_dict[current_id] = ""
|
|
else:
|
|
# 累积序列(移除可能的分隔符如空格)
|
|
fa_dict[current_id] += line.replace(" ", "")
|
|
|
|
print(f"成功读取 {len(fa_dict)} 条蛋白质序列")
|
|
|
|
# 2. 配置Firefox选项
|
|
options = Options()
|
|
options.set_preference("dom.webdriver.enabled", False)
|
|
options.set_preference("useAutomationExtension", False)
|
|
|
|
# 启用无头模式(服务器环境下必须启用)
|
|
options.add_argument("-headless")
|
|
|
|
# 3. 初始化Firefox驱动 - 明确指定geckodriver路径
|
|
# 重要:请确认下面的路径是否正确
|
|
# 可以在终端运行 'which geckodriver' 或 'find / -name geckodriver 2>/dev/null' 来确认路径
|
|
geckodriver_path = shutil.which("geckodriver") or "/usr/local/bin/geckodriver"
|
|
|
|
# 如果上面的路径不对,请尝试下面这些常见路径
|
|
# geckodriver_path = "/usr/bin/geckodriver"
|
|
# geckodriver_path = "/home/userlab/home/wutx/05.tool/geckodriver"
|
|
|
|
print(f"使用geckodriver路径: {geckodriver_path}")
|
|
|
|
try:
|
|
service = Service(executable_path=geckodriver_path)
|
|
driver = webdriver.Firefox(service=service, options=options)
|
|
print("Firefox驱动初始化成功")
|
|
except Exception as e:
|
|
print(f"驱动初始化失败: {e}")
|
|
print("请检查: 1) geckodriver路径是否正确 2) Firefox是否已安装")
|
|
sys.exit(2)
|
|
|
|
try:
|
|
# 访问目标网站
|
|
driver.get("http://www.csbio.sjtu.edu.cn/bioinf/plant-multi/")
|
|
print("成功访问Plant-mPLoc网站")
|
|
|
|
# 等待页面加载完成
|
|
wait = WebDriverWait(driver, 15)
|
|
|
|
# 4. 遍历每个蛋白质序列进行预测
|
|
processed_count = 0
|
|
success_count = 0
|
|
fail_count = 0
|
|
|
|
for protein_id, sequence in fa_dict.items():
|
|
processed_count += 1
|
|
print(f"[{processed_count}/{len(fa_dict)}] 正在处理蛋白质: {protein_id}...")
|
|
|
|
try:
|
|
# 等待输入框加载并清空
|
|
input_seq = wait.until(
|
|
EC.presence_of_element_located((By.NAME, "S1"))
|
|
)
|
|
input_seq.clear()
|
|
|
|
# 输入序列(格式:ID + 换行 + 序列)
|
|
# 简化ID格式,避免网站识别问题
|
|
simple_id = protein_id.replace(">", "").split()[0]
|
|
input_seq.send_keys(f">{simple_id}\n{sequence}")
|
|
|
|
# 查找并点击提交按钮
|
|
submit_btn = wait.until(
|
|
EC.element_to_be_clickable((By.XPATH, '//input[@type="submit"]'))
|
|
)
|
|
submit_btn.click()
|
|
|
|
# ===== 关键修改:主动处理可能出现的弹窗 =====
|
|
try:
|
|
# 给弹窗出现的时间
|
|
time.sleep(0.8)
|
|
|
|
# 切换到弹窗并获取其文本内容
|
|
alert = driver.switch_to.alert
|
|
alert_text = alert.text
|
|
print(f" 检测到弹窗,内容: '{alert_text[:100]}'")
|
|
|
|
# 接受弹窗(相当于点击"确定")
|
|
alert.accept()
|
|
print(" 已处理弹窗")
|
|
|
|
# 弹窗处理后等待页面稳定
|
|
time.sleep(0.5)
|
|
except Exception as alert_error:
|
|
# 没有弹窗是正常情况,继续流程
|
|
pass
|
|
# ===== 弹窗处理结束 =====
|
|
|
|
# 设置不监听弹窗(备用方案)
|
|
try:
|
|
driver.execute_script("window.alert = function(){};")
|
|
driver.execute_script("window.confirm = function(){return true;};")
|
|
driver.execute_script("window.prompt = function(){return true;};")
|
|
except:
|
|
pass
|
|
|
|
# 等待结果出现 - 使用更灵活的策略
|
|
try:
|
|
# 尝试第一种定位方式:查找包含"Location"的元素
|
|
result_element = wait.until(
|
|
EC.presence_of_element_located((By.XPATH, "//font[contains(., 'Location')]"))
|
|
)
|
|
except:
|
|
try:
|
|
# 尝试第二种定位方式:查找包含预测结果的表格
|
|
result_element = wait.until(
|
|
EC.presence_of_element_located((By.XPATH, "//table//td//strong"))
|
|
)
|
|
except:
|
|
try:
|
|
# 尝试第三种定位方式:查找任何包含"Location:"文本的元素
|
|
result_element = wait.until(
|
|
EC.presence_of_element_located((By.XPATH, "//*[contains(text(), 'Location:')]"))
|
|
)
|
|
except Exception as timeout_err:
|
|
print(f" 等待结果超时: {timeout_err}")
|
|
raise Exception("无法定位结果元素")
|
|
|
|
# 获取页面源码并解析
|
|
page_text = driver.page_source
|
|
tree = etree.HTML(page_text)
|
|
|
|
# 尝试多种XPath定位结果,提高容错率
|
|
location = "预测失败"
|
|
|
|
# 策略1: 原始XPath
|
|
location_elements = tree.xpath('/html/body/div/table/tbody/tr[8]/td/table/tbody/tr[2]/td[2]/strong/font/text()')
|
|
if location_elements and location_elements[0].strip():
|
|
location = location_elements[0].strip().replace('.', '')
|
|
|
|
# 策略2: 查找包含"Location:"的文本
|
|
elif not location or location == "预测失败":
|
|
alt_elements = tree.xpath('//font[contains(text(), "Location")]/text()')
|
|
if alt_elements and alt_elements[0].strip():
|
|
location = alt_elements[0].replace('Location:', '').replace('.', '').strip()
|
|
|
|
# 策略3: 查找所有包含"Location:"的元素的文本
|
|
elif not location or location == "预测失败":
|
|
all_texts = tree.xpath('//*[contains(text(), "Location:")]/text()')
|
|
if all_texts and all_texts[0].strip():
|
|
for text in all_texts:
|
|
if "Location:" in text:
|
|
location = text.replace('Location:', '').replace('.', '').strip()
|
|
break
|
|
|
|
# 策略4: 通用查找strong元素中的font文本
|
|
elif not location or location == "预测失败":
|
|
strong_elements = tree.xpath('//td//strong//font/text()')
|
|
if strong_elements and strong_elements[0].strip():
|
|
location = strong_elements[0].strip().replace('.', '')
|
|
|
|
# 策略5: 查找任何font元素的文本
|
|
elif not location or location == "预测失败":
|
|
font_elements = tree.xpath('//font/text()')
|
|
for font_text in font_elements:
|
|
if font_text.strip() and len(font_text.strip()) > 3 and "Location" not in font_text:
|
|
location = font_text.strip().replace('.', '')
|
|
break
|
|
|
|
print(f" -> 预测定位: {location}")
|
|
|
|
# 保存结果
|
|
with open(arg2, "a") as fw:
|
|
fw.write(f"{protein_id}\t{location}\n")
|
|
|
|
success_count += 1
|
|
|
|
# 返回首页准备下一个预测
|
|
driver.back()
|
|
# 等待返回完成
|
|
time.sleep(1.5)
|
|
|
|
except Exception as e:
|
|
error_msg = str(e)
|
|
print(f" -> 处理 {protein_id} 时出错: {error_msg[:150]}")
|
|
fail_count += 1
|
|
|
|
# 尝试处理弹窗错误
|
|
if "alert" in error_msg.lower() or "Alert" in error_msg:
|
|
print(f" -> 尝试处理弹窗错误...")
|
|
try:
|
|
# 尝试切换到弹窗并接受
|
|
alert = driver.switch_to.alert
|
|
alert.accept()
|
|
time.sleep(0.5)
|
|
except:
|
|
pass
|
|
|
|
# 记录失败信息
|
|
with open(arg2, "a") as fw:
|
|
fw.write(f"{protein_id}\t处理失败: {error_msg[:80]}\n")
|
|
|
|
# 刷新页面重新开始
|
|
try:
|
|
driver.get("http://www.csbio.sjtu.edu.cn/bioinf/plant-multi/")
|
|
time.sleep(2)
|
|
except:
|
|
# 如果刷新失败,尝试重新初始化驱动
|
|
print(" 页面刷新失败,尝试重新初始化...")
|
|
try:
|
|
driver.quit()
|
|
time.sleep(2)
|
|
service = Service(executable_path=geckodriver_path)
|
|
driver = webdriver.Firefox(service=service, options=options)
|
|
driver.get("http://www.csbio.sjtu.edu.cn/bioinf/plant-multi/")
|
|
time.sleep(3)
|
|
except Exception as restart_err:
|
|
print(f" 重新初始化失败: {restart_err}")
|
|
break
|
|
|
|
# 输出统计信息
|
|
print("\n" + "="*60)
|
|
print("处理完成统计:")
|
|
print(f" 总序列数: {len(fa_dict)}")
|
|
print(f" 成功处理: {success_count}")
|
|
print(f" 处理失败: {fail_count}")
|
|
print(f" 成功率: {(success_count/len(fa_dict))*100:.1f}%" if len(fa_dict) > 0 else " 成功率: N/A")
|
|
print("="*60)
|
|
|
|
except Exception as e:
|
|
print(f"主流程出错: {e}")
|
|
finally:
|
|
# 确保浏览器被关闭
|
|
try:
|
|
driver.quit()
|
|
print("浏览器已关闭")
|
|
except:
|
|
pass
|
|
print(f"\n结果已保存到: {arg2}")
|
|
|
|
|
|
def main():
|
|
"""主函数,处理命令行参数"""
|
|
# 创建命令行参数解析器
|
|
parser = argparse.ArgumentParser(
|
|
description="自动从Plant-mPLoc网站获取蛋白质亚细胞定位预测结果",
|
|
formatter_class=argparse.RawDescriptionHelpFormatter,
|
|
epilog="""
|
|
使用示例:
|
|
python %(prog)s --input ../Ft.SPL.pep.fasta --output Plant_mPLoc_out.txt
|
|
|
|
注意事项:
|
|
1. 确保已安装Firefox浏览器和geckodriver
|
|
2. 建议在服务器环境中使用无头模式运行
|
|
3. 网站结构改变时可能需要调整XPath
|
|
4. 如遇弹窗错误,脚本会自动尝试处理
|
|
"""
|
|
)
|
|
|
|
# 添加参数
|
|
parser.add_argument(
|
|
"--input",
|
|
required=True,
|
|
help="输入FASTA文件路径(包含蛋白质序列)"
|
|
)
|
|
parser.add_argument(
|
|
"--output",
|
|
required=True,
|
|
help="输出文件路径(结果将追加写入)"
|
|
)
|
|
|
|
# 解析参数
|
|
args = parser.parse_args()
|
|
|
|
# 显示启动信息
|
|
print("=" * 60)
|
|
print("Plant-mPLoc 亚细胞定位自动化预测")
|
|
print(f"输入文件: {args.input}")
|
|
print(f"输出文件: {args.output}")
|
|
print("=" * 60)
|
|
|
|
# 运行主函数
|
|
get_Plant_mPLoc_out(args.input, args.output)
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|