news 2026/9/20 19:46:05

R语言爬虫实战:从TCMSP自动抓取中药靶点并构建网络图

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
R语言爬虫实战:从TCMSP自动抓取中药靶点并构建网络图

做网络药理学的人,应该都经历过这个阶段:文献里到处都是TCMSP、OB、DL、靶点预测这些词,真到自己动手的时候,第一步取数据就被卡住了。TCMSP确实能查,但是你要把几十个成分、上百个靶点一个一个从网页上复制到Excel,再手动去重、匹配基因名,一晚上就这么过去了。我第一次做中药-靶点网络图的时候就是这么干的,后来痛定思痛,把所有能自动化的环节全部用R语言脚本化,才有了这套从网页爬虫到最终网络图输出的完整流程。

这篇文章我不讲虚的,直接把整个流程拆开给你看:怎么分析TCMSP的请求结构,怎么写爬虫脚本,怎么用R语言清洗数据,怎么构建中药-靶点网络图,以及我踩过哪些坑。全文用一套真实的代码串下来,你只要能跑通R,跟着抄就行。

1. 项目概述:为什么要把TCMSP、R和爬虫放在一起

1.1 这个项目到底在解决什么问题

中药-靶点网络分析的常规操作是:选定一味中药,在TCMSP数据库里查到它的活性成分,再查每个成分对应的靶点蛋白,最后把这些关系画成一张网络图。听起来很简单,但实际执行的时候你会发现三个痛点。

第一个痛点是数据量大。一味中药通常有几十个甚至上百个化学成分,每个成分又对应多个靶点,一个项目下来动辄上千条关系记录。手动复制粘贴不仅慢,而且容易出错——我见过有人把两行数据贴反,导致后面整个靶点富集分析都错了。

第二个痛点是数据格式不统一。TCMSP返回的表格里有成分ID、分子名称、OB值、DL值、靶点名称等十几列,有些列名在不同页面里还不一样。直接下载下来用Excel打开,中文可能乱码,列名可能有空格,目标基因名称时而是标准Symbol、时而是UniProt ID,这些都需要清洗。

第三个痛点是重复工作。今天分析黄芪,明天分析丹参,后天分析一个复方,如果每次都手动操作,同样的清洗逻辑要写三遍。但只要你把爬虫和清洗脚本封装成函数,换一味药只是改一个参数的事。

所以我做这个项目的目标很明确:输入一位中药的英文名或拼音,输出一张可以直接放进论文里的中药-靶点网络图,中间所有环节都自动化。

1.2 为什么选TCMSP而不是其他数据库

搞药物靶点预测的数据库其实不少,比如STITCH、SwissTargetPrediction、Batman-TCM,但我个人最常用的还是TCMSP。原因有几点。

TCMSP的全称是Traditional Chinese Medicine Systems Pharmacology Database and Analysis Platform,由西北农林科技大学团队开发,2014年发表在Journal of Cheminformatics上,算是中药网络药理学领域引用率最高的数据库之一。它的数据覆盖面广,包含了近500味中药材、3万多个化学成分、3千多个靶点以及相关的疾病信息,尤其适合做中药全成分分析。

另外它的数据字段是现成的,OB(口服生物利用度)和DL(类药性)这两个筛选指标直接列在表格里,不需要自己再去其他数据库计算。做网络药理学的时候,这两个指标几乎绕不开,TCMSP直接给出来就能省很多事。

TCMSP的劣势是网页技术比较老旧,批量操作极其不友好。这个数据库没有提供公开的API接口,想要自动拿数据就必须走网页请求的路子。这就引出了下面的话题:所谓的爬虫,本质上就是把浏览器里手动点击的过程,变成用代码发HTTP请求的过程。

1.3 为什么流程搭建选择R语言而不是Python

说到爬虫,大多数人第一反应是Python,这没有错。但我的场景比较特殊,因为整个分析链条的后半段——数据清洗、网络构建、可视化——我是打算在R里完成的。如果爬虫用Python,那我就要在两套语言之间反复切换,数据还得通过CSV文件中转,流程上多出不少麻烦。

R语言在生物信息学领域有天然优势,尤其是Bioconductor体系的包,比如org.Hs.eg.db做基因ID转换、clusterProfiler做富集分析,这些都是Python生态里没有的对等替代。rvest包做HTML表格解析也足够顺手,处理TCMSP这种老式网页完全够用。

如果你本身熟悉Python,也可以用requests+BeautifulSoup完成爬虫部分,最后把结果存成CSV再给R用。这两种方案我都试过,但最终保留了R单语言方案,收益是流程更好维护,一个脚本从头跑到尾,不容易在语言切换的过程中丢信息。

2. 环境准备与包管理:先把地基打好

2.1 R和RStudio的基础安装

如果你电脑上还没有R环境,先去CRAN的国内镜像下载R安装包,安装的时候保持默认选项即可。装完之后我建议再装一个RStudio,它不是必需的,但确实好用,代码高亮、变量查看、绘图预览都方便很多。R语言本身是一个解释型语言,安装完成后打开RStudio,在Console窗口输入version,能看到版本信息就说明环境没问题。

TCMSP相关的分析对R版本没有特殊要求,3.6以上就能跑,但如果你要用最新版的dplyr或ggplot2,还是建议把R升级到当前的最新稳定版。老版本的R在安装某些依赖包的时候会报错,比如tidyverse里的某些包要求R版本不低于4.0,这一点装包的时候注意看提示就行。

2.2 需要安装的R包清单与作用

这个项目会用到这么几类包,我按功能列一下,方便你对照安装。

  • rvest:核心爬虫包,用于发送HTTP请求和解析HTML表格,本项目的爬虫部分全靠它。
  • httr:底层请求工具,处理User-Agent、Referer、Cookie等细节,很多时候需要和rvest搭配使用。
  • dplyr和tidyr:数据清洗利器,负责筛选OB/DL值、去重、列名重命名等操作。
  • stringr:字符串处理,比如从靶点名称里去掉多余空格、统一大小写。
  • igraph:网络分析核心包,负责构建图和计算网络属性。
  • ggraph:基于ggplot2的网络可视化包,画出来的图比igraph自带绘图函数美观得多。

安装命令很简单,在RStudio里一行搞定。

install.packages(c("rvest", "httr", "dplyr", "tidyr", "stringr", "igraph", "ggraph"))

如果你安装ggraph时遇到依赖问题,通常是因为它的底层依赖tidygraph和graphlayouts还没装好。可以先把这两个包装上,再回头装ggraph,这样报错概率低很多。

2.3 项目目录结构的设计思路

动手写代码之前,建议先规划好项目目录。我的习惯是建一个项目文件夹,里面划分成scripts、data、output三个子目录。scripts放R脚本,data放原始爬取的数据,output放清洗后的表格和网络图文件。

这个分法看起来很基础,但实际项目中能省下不少事。TCMSP爬虫脚本需要跑一段时间,中间可能会断,跑出来的数据先存成RDS格式存放在data目录,即使后续脚本改坏了,也不用从头再爬一遍。R语言里保存中间数据用的是saveRDS()和readRDS(),比反复读写CSV要快,而且能保留数据类型信息。

3. 拆解TCMSP的请求结构:爬虫前必须先学会看网页

3.1 用浏览器开发者工具查真实请求

写爬虫之前最重要的一步,是搞清楚TCMSP网页提交请求时到底发了一个什么样的HTTP请求。很多人一上来就写代码,结果怎么都抓不到数据,问题往往出在这里。

以我目前使用的情况来看,TCMSP的入口地址是一个PHP文件,你在首页搜索框里输入草药名称,点击搜索之后,浏览器会向服务器发送一个带参数的GET请求。参数里有两个关键字段,一个表示搜索关键字,另一个表示搜索类型,比如搜索草药时类型就是herb_all,搜索某个具体成分时类型就是mol_all。

验证方法很直接:在浏览器里打开TCMSP首页,按F12进入开发者工具,切到Network面板,然后在搜索框里输入黄芪的英文名Astragalus,点击搜索。观察Network面板里新出现的那个请求,点开看它的Query String Parameters,就能看到实际发送的参数名和值。这个操作每次写爬虫前都要做一遍,因为网站改版后参数名可能会变,直接抄旧代码很可能失效。

3.2 用httr包模拟请求拿到HTML

确认好请求地址和参数之后,用httr包模拟请求就很简单了。核心思路是把参数放进query列表,同时设置User-Agent伪装成浏览器,避免被服务器拒绝。

library(httr) library(rvest) base_url <- "http://tcmsp-e.com/tcmsp.php" resp <- GET( base_url, query = list( qr = "Astragalus", qsr = "herb_all" ), add_headers( `User-Agent` = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0 Safari/537.36", `Referer` = "http://tcmsp-e.com/" ), timeout(30) ) if (resp$status_code == 200) { page <- content(resp, as = "parsed", encoding = "UTF-8") tables <- html_table(page, fill = TRUE) message("成功获取页面,共解析到 ", length(tables), " 张表格") } else { message("请求失败,HTTP状态码:", resp$status_code) }

这一步是整个项目的起点。status_code返回200表示请求成功,如果返回403或503,多半是User-Agent没设置好,或者请求频率太高被暂时限制了。遇到这种情况,先检查请求头,再考虑降低访问频率。

3.3 解析HTML表格时怎么定位目标表

html_table()返回的是一个列表,列表里每一个元素就是网页中的一张表格。问题在于TCMSP的结果页面包含多张表,有筛选栏、有成分列表、有页脚信息,你不能假设第1张表就是要的数据。

我的做法是先循环检查所有表格的列名,打印出来看一眼,再根据列名判断哪张是成分表。

for (i in seq_along(tables)) { cat("表格", i, "的列名为:", paste(colnames(tables[[i]]), collapse = " | "), "\n") }

通常成分表的列名里会包含MOL ID、Molecule Name、OB(%)这些字段。定位到目标表之后,再把它单独提取出来。TCMSP返回的表格列名可能有空格或特殊符号,比如OB(%),这时候在dplyr里操作要用反引号包裹列名,否则会报错。

4. 数据抓取完整实操:从一味药到完整的成分-靶点关系表

4.1 抓取中药成分列表并记录原始数据

拿到HTML并定位到成分表之后,下一步是提取成分列表,并且立刻把原始数据保存一份。这一步不要急着清洗,先存档再说。

herb_raw <- tables[[target_index]] saveRDS(herb_raw, "data/herb_raw.rds")

保存原始数据的好处是,哪怕后面清洗逻辑写错了,也可以随时回到起点重新来。你也不需要每次调试都重新访问TCMSP,既省时间又避免对公共数据库造成压力。

有一点要提醒:TCMSP的成分列表并不直接等于中药的活性成分,它只是这个药材里检测到的化学成分集合。究竟哪些算活性成分,需要后面的OB和DL指标来筛选。所以这一步你不用动手砍数据,把全量成分都保留下来,后面再做判断。

4.2 根据成分ID逐个抓取靶点

成分列表里每一行都有一个MOL ID,它是TCMSP里每个化学分子的唯一编号。接下来我们需要拿着这个编号去请求成分详情页,从详情页里解析出靶点表格。

这里涉及一个循环请求的过程,是整个项目里耗时最长的环节。以黄芪为例,TCMSP里收录了大约80多个化学成分,抓取每个成分的靶点页面需要几秒钟,整个循环跑下来大概三四分钟。如果换成复方,几百个成分循环一遍就要比较久了。

循环里一定要控制请求频率,每次请求之间至少间隔2秒,我习惯用Sys.sleep(3),宁可慢一点也不要触发服务器的限流机制。代码结构大致如下。

mol_ids <- herb_raw$`MOL ID` target_list <- list() for (mol_id in mol_ids) { resp <- GET( base_url, query = list(qr = mol_id, qsr = "mol_all"), add_headers( `User-Agent` = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Chrome/120.0 Safari/537.36" ), timeout(30) ) page <- content(resp, as = "parsed", encoding = "UTF-8") tab <- html_table(page, fill = TRUE) # 找到包含靶点信息的目标表,这里以列名里出现Gene name或Target为判断依据 target_tab <- NULL for (t in tab) { if (any(grepl("Gene|Target", colnames(t)))) { target_tab <- t break } } if (!is.null(target_tab)) { target_tab$MOL_ID <- mol_id target_list[[mol_id]] <- target_tab } Sys.sleep(3) } all_targets_raw <- do.call(rbind, target_list) saveRDS(all_targets_raw, "data/all_targets_raw.rds")

这里有一个细节值得注意:循环里对每个成分都做了tryCatch式的判断,即使某个成分页面解析失败,也不会中断整个流程,最多就是丢掉这一个成分的数据。实际运行的时候,我碰到过个别MOL ID请求反复超时的情况,这种通常是网站服务器临时不稳定,稍后重跑一次脚本就能补上。

4.3 批量请求时的网络异常处理

采集环节最大的敌人是网络不稳定,而不是你代码写错。我在实际跑脚本时遇到过几次情况:连续请求几十个页面之后,服务器开始返回空页面,status_code还是200,但解析出来没有任何表格。这种问题非常隐蔽,因为程序没有报错,表面上看一切正常,实际数据已经丢了。

解决办法是加一层校验,在解析表格之后检查结果是否为空,如果为空就重试。重试次数可以设置成3次,每次重试前等待更长的时间,比如10秒。这种过载保护机制在正式运行脚本时很有必要,尤其是当你需要一口气抓几百个成分的时候。

retry_count <- 0 while (retry_count < 3 && is.null(target_tab)) { Sys.sleep(10) # 重新请求和解析 retry_count <- retry_count + 1 }

4.4 把成分和靶点合并成一张关系表

靶点抓完之后,我们手上有了两份数据:一份是成分信息表(herb_raw),一份是成分-靶点对应表(all_targets_raw)。下一步是把它们合并成分析用的关系表。

合并的目标很明确,就是构造一个包含三列的数据框:成分名称、成分ID、靶点基因名。这里的关键是搞清楚哪一列是靶点基因名。TCMSP靶点表里不同版本给出的列名不完全一样,有时候是Gene name,有时候是Target,还有时候直接给UniProt ID。你要根据实际抓取到的列名做调整。

library(dplyr) relations <- all_targets_raw %>% left_join(herb_raw %>% select(`MOL ID`, `Molecule Name`, `OB(%)`, DL), by = "MOL ID") %>% rename( compound = `Molecule Name`, target = `Gene name` ) %>% select(compound, target, MOL_ID = `MOL ID`, OB = `OB(%)`, DL) %>% filter(!is.na(target), target != "") %>% distinct()

合并完之后一定要做distinct去重,因为同一个成分对同一个靶点可能多次出现,网络图里重复的边没有任何意义。

5. 数据清洗与核心阈值筛选:别让垃圾数据毁了你的网络图

5.1 OB和DL阈值怎么定才有说服力

TCMSP里面存储的是全量化学成分数据,这并不意味着每个成分都要进入后续分析。口服生物利用度OB表示药物经口服后被机体吸收进入循环系统的速度和程度,类药性DL用来衡量一个化合物与已知药物在结构上的相似程度。这两个值越高的成分,理论上越有可能成为发挥药效的活性成分。

目前学术界使用最广泛的标准是OB大于等于30,DL大于等于0.18,这个标准最早来自TCMSP数据库自身的推荐,后续大量文献沿用,已经形成了一个约定俗成的参考线。我自己的习惯是筛选的时候用这两个指标,但在论文里会明确写出筛选标准,并且把筛选前后的成分数量对比列出来,这样审稿人看了会更信服。

active_compounds <- relations %>% filter(OB >= 30, DL >= 0.18) %>% distinct(compound, MOL_ID, OB, DL)

有一个容易忽略的地方:OB和DL筛选应该作用在成分层面,而不是关系层面。你先通过成分表筛出符合条件的活性成分,再拿这些成分去关联靶点,而不是先把所有关系表建好再按OB和DL过滤关系行。两者结果可能有细微差别,逻辑上前者更清晰。

5.2 靶点名称的统一与ID转换

TCMSP返回的靶点基因名通常用的是官方Symbol,比如PTGS1、ESR1、NOS3这种格式,直接拿来做网络图没有问题。但如果你后续要做通路富集分析,或者要跟疾病靶点取交集,最好把基因Symbol统一转换为Entrez ID或Ensembl ID,这样不同数据源之间才能精确匹配。

R里面做ID转换用的最多的是Bioconductor的org.Hs.eg.db包。这个包装起来比普通CRAN包稍微麻烦一点,需要用BiocManager安装。

if (!requireNamespace("BiocManager", quietly = TRUE)) install.packages("BiocManager") BiocManager::install("org.Hs.eg.db")

转换逻辑很简单,把基因Symbol作为key,映射到Entrez ID即可。

library(org.Hs.eg.db) symbols <- unique(relations$target) entrez_map <- AnnotationDbi::mapIds( org.Hs.eg.db, keys = symbols, keytype = "SYMBOL", column = "ENTREZID" )

需要说明的是,mapIds在某些基因映射不到时会返回NA,这些缺失值需要人工检查一下,我遇到过TCMSP的靶点列表里含有非人类基因的情况,这在做人体靶点分析时需要剔除。

5.3 关系表里隐含的常见脏数据

清洗关系表时最烦的不是格式问题,而是语义层面的杂质。我举几个实际遇到过的例子。

有些靶点名称里带有括号注释,比如ESR1 (estrogen receptor 1),实际上gene symbol只是ESR1。直接用这个带注释的字符串去做网络图,你会看到两个节点,一个是ESR1,一个是ESR1 (estrogen receptor 1),数据被错误拆分成两个靶点。处理方式是用正则表达式把括号里的注释去掉,只保留前面的标准化名称。

还有些成分名称本身会重复,同一个化学成分在不同列表里出现了多次,合并的时候如果不做distinct,网络图的边就会重复计算,节点之间的连线条数虚高,影响后续度中心性的计算。

另外,TCMSP靶点表里我见过空行和占位符,比如某些行只有MOL ID,靶点列是空的或者一个横杠。这些行在构建网络图时必须剔除,不然igraph会把它当成一个名称是NA的节点,导致画图的时候报错。

5.4 多成分对应同一靶点的去重逻辑

网络分析中还有一个细节,就是多成分对同一靶点的关系如何处理。假设黄芪里有10个成分都作用在PTGS1上,那么在边表里会有10条记录都是compound到PTGS1。igraph会自动把它们变成10条平行边,画出来的网络图上两个节点之间会有10根线叠在一起,非常难看。

处理方式看你分析的目的。如果只是想展示成分与靶点之间的关联关系,建议保留一条边;如果你想在节点或边的属性里记录成分数量,那可以在去重之前先统计次数,把次数作为边的权重属性存下来。

network_edges <- active_relations %>% group_by(compound, target) %>% summarise(weight = n(), .groups = "drop")

这样处理之后,边的数据里多了一列weight,后续在网络图里可以把weight映射为边的粗细或透明度,既美观又保留了原始信息。

6. 中药-靶点网络图构建与可视化:让你的数据变成一张能发表的好图

6.1 用igraph构建网络对象

igraph是R语言里最经典、最稳定的网络分析包。构建网络的第一步是加载igraph库,然后通过graph_from_data_frame函数,把边表转换成图对象。

library(igraph) g <- graph_from_data_frame(network_edges[, c("compound", "target")], directed = FALSE)

这里directed=FALSE表示构建无向网络,因为成分和靶点之间的作用关系本身不分方向。如果你后续想分析调控方向,比如激活或抑制,那就需要用有向图,但TCMSP本身的数据不包含这类信息,所以通常用无向图就够了。

构建完图对象之后,可以顺手给节点加一个类型属性。节点分为成分和靶点两类,加这个属性是为了画图时用颜色区分不同类型,也方便后续做网络拓扑分析。

V(g)$type <- ifelse(V(g)$name %in% network_edges$compound, "compound", "target")

网络构建完成后,用summary(g)看一下节点数和边数。如果节点数跟你的预期差距很大,比如莫名多出几十个节点,赶紧回去查数据清洗那一步,大概率是靶点名称里混入了杂质。

6.2 用ggraph美化网络图的实操代码

igraph自带的plot函数能快速出图,检查数据结构够用,但要放进论文或汇报材料里就不太够看了。我推荐用ggraph包做美化,它基于ggplot2的语法体系,出图风格统一,而且可定制性很强。

library(ggraph) library(tidygraph) tg <- as_tbl_graph(g) p <- ggraph(tg, layout = "kk") + geom_edge_link(aes(width = weight), alpha = 0.3, color = "grey60") + geom_node_point(aes(color = type), size = 3) + scale_color_manual(values = c(compound = "#E76F51", target = "#2A9D8F")) + scale_edge_width(range = c(0.5, 2)) + theme_void() + theme(legend.position = "bottom") ggsave("output/network_ggraph.png", p, width = 8, height = 6, dpi = 300)

layout = "kk"表示使用Kamada-Kawai布局算法,这种布局在节点数量不算太多的时候表现很好,节点之间的相对位置能比较直观地反映拓扑距离。如果你发现画的图太挤,可以换成layout = "fr",是Fruchterman-Reingold算法,对中等规模网络的可读性更好。两个都试试,看哪个顺眼用哪个。

6.3 节点太多时怎么让图更清晰

中药-靶点网络最常遇到的问题就是节点太多,画出来一团黑。活性成分加对应靶点,动不动就是上百个节点,全部画在一张图里必然杂乱。

我常用的做法是按节点度数做过滤。度数指的是一个节点连接了多少条边,在网络里度越高的节点通常越重要。如果一张图上节点太多,可以先只保留度排名前50的节点,其余藏在布局里的小节点暂时不放出来。

deg <- degree(g) top_nodes <- names(sort(deg, decreasing = TRUE))[1:50] g_pruned <- induced_subgraph(g, top_nodes)

这个方法特别适合做PPT汇报,先展示核心子网络,再展开说明全网络。网络上还有一个通用技巧,就是把节点标签藏起来。节点多到一定程度,标签只会互相遮挡,根本看不清,不如导出图片后在后期工具里单独标注重点节点。

6.4 导出为Cytoscape可用的GraphML格式

igraph绘制的图适合做快速浏览和汇报,但如果你要深入研究网络拓扑属性,或者把网络拿去跟疾病靶点做交集分析,我建议导出到Cytoscape里操作。Cytoscape是专门做生物网络可视化的软件,很多网络药理学论文里的精美网络图都是在Cytoscape里完成的。

igraph导出Cytoscape格式非常简单,GraphML是一种通用的XML格式,Cytoscape可以直接打开。

write.graph(g, "output/tcmsp_network.graphml", format = "graphml")

打开Cytoscape之后,用File > Import > Network from File选择这个graphml文件即可。导入后节点类型和边的权重属性都会保留,你可以用Cytoscape的样式编辑器给成分和靶点设置不同的形状和颜色,也能用它的Network Analyzer插件直接计算度中心性、介数中心性等指标。

7. 常见问题排查实录:这些坑我替你已经踩过了

7.1 网页表格解析出来是空行或0行

这个问题我在TCMSP改版期间遇到过,原因多半是html_table()解析时,表格里有些行是合并单元格或者嵌套表格。一般情况下可以先试一下html_table的fill参数,正常情况下填TRUE就不会报错。如果还是解析不出来,改用更底层的办法,直接抽取所有td单元格内容。

cells <- page %>% html_nodes("table td") %>% html_text()

拿到的cells是一个文本向量,再根据你已知的列数手动切分成数据框。这属于暴力解法,但确实能解决一些表格嵌套造成的解析问题。

7.2 中文药名搜索时返回异常结果

TCMSP虽然支持中文或拼音检索,但爬虫请求时涉及URL编码问题。我建议直接在请求参数里使用药材的标准拉丁名或英文名,比如黄芪用Astragalus,丹参用Salvia miltiorrhiza,这样能避免编码不一致带来的麻烦。

如果你确实需要按中文名搜索,记得先用URLencode()对中文进行编码再放进query里。R中可以用以下方式处理。

keyword <- URLencode("黄芪", reserved = TRUE)

另外要确认TCMSP的qsr参数是herb_all还是herb_name。不同搜索模式下参数值不同,直接看浏览器Network面板最靠谱。

7.3 网络图节点数比预期多很多

节点数异常增加的根源,基本都在数据清洗环节。最常见的原因是靶点列里混入了一列非靶点信息,比如把靶点表的序号列或蛋白描述列误当成基因名。排查方法很简单,检查relations表里target列的唯一值数量,然后随机抽几个值去TCMSP页面人工比对。

还有一种情况是成分列里有多余的空白字符串,导致igraph创建了一个名字为空的节点。清洗时用filter(!is.na(compound), compound != "")把空值去掉,问题就能解决。

7.4 请求过于频繁被服务器拒绝

TCMSP是公共学术数据库,没有强反爬机制,但如果你在短时间内发起大量请求,服务器还是会返回异常响应。我在跑复方成分的时候有过一次惨痛教训:脚本里忘记加Sys.sleep,连续请求了三百多次,跑到一半开始出现大量空响应,页面解析结果全部缺失,最后被迫从头再来。

我的建议是每次请求之间至少等待2到3秒,批量抓取上百个成分时,把间隔拉长到5秒。这种看似低效的做法,实际运行下来反而更高效,因为你不用反复重试,也不会触发限流。另外,尽量在工作时间非高峰时段运行脚本,比如上午或者深夜,对数据库服务器也更友好。

7.5 保存的CSV在Excel里打开乱码

如果你把清洗好的数据保存成CSV然后用Excel打开,很可能会看到中文乱码。原因是R写CSV默认用UTF-8编码,而Windows版的Excel默认按本地编码解析。解决方案有两个:一是用write.csv的时候加上fileEncoding = "UTF-8-BOM",这样Excel能识别;二是干脆存成RDS或xlsx格式,避开编码问题。

write.csv(clean_data, "output/clean_data.csv", row.names = FALSE, fileEncoding = "UTF-8-BOM")

如果是你自己后续在R里继续分析,我其实最推荐saveRDS(),RDS格式读取速度快、数据类型不会丢失,是R语言内部交换数据的最佳选择。

8. 这套流程还能怎么延伸:从单味药到复方和疾病靶点

这套自动化流程的价值不在于跑通一味药,而在于把方法复用到更复杂的场景里。我做完单味药分析之后,立刻把代码封装成了函数,默认参数是药材名称和保存路径,这样下次分析其他药材,一行代码就能启动。

往复方方向扩展时,只需要把多味药材的成分表合并后再去重。比如你分析一个含有5味药材的方子,每味药材抓一次成分列表,合并之后做OB和DL筛选,再去抓靶点,网络图就自动变成复方-靶点网络。这个网络里还能进一步区分某个成分来自哪几味药材,算是一张更复杂的二分网络,扩展价值很高。

往疾病方向扩展时,可以下载DisGeNET或GeneCards的疾病靶点数据,跟TCMSP预测靶点取交集,就能筛选出中药作用于疾病的关键靶点。再配合clusterProfiler做GO和KEGG富集分析,就是一篇标准网络药理学论文里从预测到机制的核心数据链条。

我在实际做课题的时候,通常是把R语言爬虫出数据、igraph网络分析、clusterProfiler富集分析三个环节串成一个完整的R脚本,跑完自动输出所有图表。前期搭建脚本比较费时间,但一个流程跑顺之后,后续每换一味药、一个方子,基本就是改一个参数的事。个人最深的体会是,网络药理学分析里那些看起来高深的网络图,真正决定成败的反而是最基础的取数环节,数据取干净了,后面所有的分析都是锦上添花;数据一旦是脏的,后面跑得再漂亮的图也只是自我安慰。希望这套流程能帮你少走一些我当时走过的弯路。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/9/20 19:44:36

光伏电池建模与MPPT控制:从Simulink仿真到SVPWM并网全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 19:43:44

火电异常检测后台实战:DCS数据接入、孤立森林算法与部署要点

简介&#xff1a;这套火电异常检测系统后台源码包&#xff0c;面向电力行业数据分析与机器学习开发者&#xff0c;聚焦火力发电过程中的设备故障与运行异常识别。项目综合运用异常检测、机器学习与深度学习模型&#xff08;如自编码器、GAN&#xff09;&#xff0c;对运行数据实…

作者头像 李华
网站建设 2026/9/20 19:43:32

JVM高频面试题实战解析:内存模型、类加载与垃圾回收调优

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 19:42:54

FX3U-ENET-L以太网模块参数设置与MC协议通信调试全指南

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

作者头像 李华
网站建设 2026/9/20 19:40:42

MNIST机器学习工程实践:5种模型对比与参数化调优

简介&#xff1a;本资源是合肥工业大学2023年《机器学习》课程大作业的完整实现方案&#xff0c;面向计算机、电子信息工程、数学等专业的本科生&#xff0c;聚焦MNIST手写数字识别这一经典任务&#xff0c;系统对比逻辑回归、SVM、FNN、CNN与RNN五类主流模型的建模思路与性能表…

作者头像 李华