R Markdown是现代R上我最喜欢的东西之一。它提供了一种在单个文档中组合文本,R代码和R代码结果的简便方法。 当该文档以HTML格式呈现时,您可以与HTML小部件(例如用于表格的DT或用于地图的传单)进行一些用户交互。 (如果您不熟悉R Markdown,可以先查看我的R Markdown视频教程 ,然后再回到这里。)

但是您可能不知道,还有一种方法可以进一步增强R Markdown的交互性:通过在文档标题中添加runtime: shiny

[ 在我们的视频教程系列中获得Sharon Machlis的R技巧 。 | 阅读InfoWorld教程: 学习使用R处理大数据 。 • 如何重塑R中的数据 。 • 触手可及的R数据操作技巧 • R的 初学者指南 。 | 通过InfoWorld大数据报告新闻通讯了解最新的分析和大数据。 ]

Shiny是R的Web应用程序框架。作为框架,它具有相当特定的结构。 但是,您可以将R Markdown文档转换为Shiny应用程序, 而不必遵循很多固定的结构 。 相反,您可以直接进入并开始编码,而不必担心一些典型的Shiny任务,例如确保在深层嵌套的布局函数中所有括号和逗号正确。

实际上,即使您是经验丰富的开发人员,R Markdown文档对于不需要完整应用程序的快速任务或快速尝试代码仍然很有用。 它仍然需要一个Shiny服务器,但是如果您已经安装了RStudio和Shiny软件包,则您已经在本地安装了其中一个。

让我们看一下R Markdown中运行时闪亮的工作原理。

1.基本R降价

我将从一个常规的,非发光的R Markdown文档开始,该文档的特征是可通过马萨诸塞州的邮政编码搜索数据。 用户可以按任何表列进行搜索或排序,回答诸如“哪个邮政编码在米德尔塞克斯县的家庭收入中位数最高?”之类的问题。 或“哪些邮政编码是每月住房价格最高的?”

Sharon Machlis / IDG

交互性受限制的常规R Markdown文档:可搜索,可排序的表。

该文档还具有一个直方图,显示了家庭收入中位数的分布,并指出了邮政编码中收入最高和最低的文本。 该表是交互式的,但文档的其余部分不是交互式的。 您可以在RStudio的RPubs上查看呈现HTML版本。

如果您想继续学习,可以在GitHub上查看此R Markdown文档的独立版本的代码-包括数据。 或者,如果您想了解如何将人口统计数据放入R中,则本文中的R代码可创建您自己的数据集(您可以调整代码以选择其他状态)。 如果您创建自己的数据版本,则使用单独的数据文件的基本R Markdown文档的代码也位于GitHub上。

无论选择哪个R Markdown文档,您都会看到它是一个具有某些交互性的大部分静态的文档。 但是,如果我希望整个文档都是交互式的,在这种情况下,请参见直方图和文本更改以及表格? 用户如何能够选择各个城市并查看所有过滤后的信息,以便仅针对那些地方显示?

一种解决方案是为每个城市生成一个页面-如果使用所谓的参数化报告,则可以使用R脚本。 但是,您也可以创建一个功能类似于交互式应用程序的R Markdown文档。

添加闪亮的互动

要将Shiny交互性添加到常规的R Markdown文档中,首先需要在文档的YAML标头中添加runtime: shiny ,例如:

---title: "Median Household Income by ZIP Code"output: html_documentruntime: shiny---

完成该操作并按“保存”后,RStudio中的编织图标将变为“运行文档”。 即使输出仍然显示“ html_document”,也不再是纯HTML。 现在它是一个迷你发光应用程序。

Sharon Machlis / IDG

常规R Markdown文档在RStudio中具有编织图标。

沙龙·马克斯(IDG)

将运行时:Shiny添加到R Markdown文档时,RStudio中的编织图标将变为“运行文档”。

让用户做出数据选择

现在,我需要一种让用户进行数据选择的方法。 Shiny为此具有许多“输入小部件”。 我将使用selectInput() ,它会创建一个下拉列表,并允许用户选择多个项目。 Shiny还有其他用于单选按钮,文本输入,日期选择器等的小部件。 您可以在RStudio的Shiny Widgets Gallery中看到它们的集合。

我的微型应用程序的selectInput()下拉列表的代码具有五个参数,如下所示:

selectInput("mycities", "Choose 1 or more cities: ",  choices = sort(unique(markdowndata$City)),   selected = "Boston", multiple = TRUE)

selectInput()的第一个参数mycities是我选择用来存储用户选择的任何值的变量名称。 第二个参数是标题文本,将与下拉列表一起显示。 第三个参数choices是下拉列表中所有可能值的向量-在这种情况下,我的数据中城市名称的唯一值按字母顺序排序。 selected = Boston表示下拉菜单将默认为波士顿为所选城市(选择默认选择是可选的)。 最后, multiple = TRUE允许用户一次选择多个城市。

此代码创建HTML下拉列表。 如果您在R控制台中运行该selectInput()代码,它将为下拉列表生成HTML(假设您已加载Shiny以及名为Citydown列的名为markdowndata的数据框)。

接下来,我需要写一些R,以便此下拉列表实际起作用。

创建动态变量

我将分两部分编写此交互逻辑:

  1. 创建一个数据框(我将其称为mydata该数据框在用户每次选择城市时都会进行过滤。
  2. 编写文本,直方图和数据表的代码,这些代码都将根据我的动态数据框架而变化。

此时要记住的最重要的事情是这些对象不再是“常规” R变量。 它们是动态的 。 它们根据用户操作而改变 。 这意味着它们的工作方式与您可能习惯的变量略有不同。

他们有什么特别之处? 这是您需要了解的三件事:

  1. 要访问存储来自用户的信息的输入变量的值,您需要语法input$myvarname ,而不仅仅是myvarname 。 因此,对于存储在mycities下拉列表中的值,请使用input$mycities
  2. 依赖于用户值的图形和表格之类的对象也是动态的,需要进行React。 这就像将它们包装在特殊功能中一样容易,但是您需要记住要这样做 。 也不能仅通过名称访问它们,还需要括号:像myvar()这样的语法,而不是myvar
  3. 当您显示动态内容时(一次又一次显示表格,地图,直方图甚至是文本),通常需要使用Shiny的特殊渲染功能之一以特殊方式进行渲染。 好消息是,Shiny负责监视更改和计算结果的大部分功能。 您只需要知道要使用哪个功能,然后将其包含在代码中即可。

这往往比听起来容易得多。 这是我将创建一个名为mydata的数据框的方式,该数据框每次用户通过mycities selectInput()下拉列表选择城市时都会更改:

mydata <- reactive({
filter(markdowndata, City %in% input$mycities)
})

mydata对象现在包含一个React表达式,并且每次用户在控制mycities的下拉列表中进行更改时, mydata对象都会更改其值。

显示动态变量

现在,我想使用过滤后的mydata数据对表进行编码。

您可能已经猜到了, DT::datatable(mydata)无法正常工作。 原因有两个。

首先,由于mydata是React式表达式,因此不能仅通过名称来引用它。 它后面需要括号,例如mydata()

但是,第二, DT::datatable(mydata())也不可用作独立代码。 您将收到类似以下的错误消息:

 Operation not allowed without an active reactive context. (You tried to do something that can only be done from inside a reactive expression or observer.) 

刚开始时,您可能会经常看到此错误消息的版本。 这意味着您正在尝试使用常规R语法显示动态内容。

为了解决这个问题,我需要一个Shiny render函数 。 几种可视化程序包具有自己的特殊Shiny渲染功能,包括DT。 它的render函数是renderDT() 。 如果我在DT代码周围添加renderDT ({ })并再次运行文档,那应该可以。

这是我的表代码:

renderDT({  DT::datatable(mydata(), filter = 'top') %>%    formatCurrency(4:5, digits = 0) %>%    formatCurrency(6, currency = "", digits = 0)   })

注意:除了创建和显示表之外,此代码还添加了一些格式。 第4列和第5列显示为货币,并带有美元符号和逗号。 列6的第二个formatCurrency()行将逗号添加到不带美元符号的舍入数字中,因为我将“”指定为货币符号。

我可以使用另一个Shiny渲染函数renderPlot()使用相同的mydata()React性数据帧创建直方图。

renderPlot({ggplot2::ggplot(mydata(), aes(x = MedianHouseholdIncome)) +  geom_histogram(binwidth = 20000, color = "black", fill = "darkgreen") +  theme_classic() +   xlab("") +  ylab("")  +   scale_x_continuous(labels = dollar)})

该代码还包含一些ggplot样式,例如为条形轮廓选择颜色并填充并更改图形的主题。 最后一行格式化x轴以添加美元符号和逗号,并且它需要scales软件包。

就像常规Markdown文档中的任何其他R代码块一样,这些R代码块中的每个块都必须位于R Markdown R代码块内。 看起来可能类似于下面的代码,该代码也将块命名为“ histo”(名称是可选的),并以英寸为单位设置绘图的宽度和高度。

```{r histo, fig.width = 3, fig.height = 2}renderPlot({ggplot2::ggplot(mydata(), aes(x = MedianHouseholdIncome)) +  geom_histogram(binwidth = 20000, color = "black", fill = "darkgreen") +  theme_classic() +   xlab("") +  ylab("")  +   scale_x_continuous(labels = dollar)})```

如果我想显示随用户选择而变化的交互式文本,则需要一个名为renderText() !的Shiny渲染函数renderText() 。 您可以将其放在代码块中,或在代码块之外使用替代的R Markdown语法格式,如下所示:

I have some plain text and then add  `r R CODE WILL BE EVALUATED HERE`

语法是一个反引号,后面紧跟一个小写的r,一个空格,要评估的R代码,并以另一个反引号结束。 因此,要为直方图添加动态标题,可以使用如下代码:

Histogram for `r renderText({input$mycities})`

这对于单个城市来说效果很好。 但是,如果有多个城市,则该代码将只显示名称,而不会在名称之间加逗号,例如Boston Cambridge Amherst 。 对于面向公众的代码,您可能需要使用基础R的paste()函数进行一些修饰:

Histogram for `r renderText({paste(input$mycities,  sep = " ", collapse = ", ")})`

您可以使用类似的代码来生成文本,该文本告诉用户收入中位数最高和最低的邮政编码。 对于这些计算,我创建了一个React性数据框,其中包含家庭收入最高的行,而另一数据记录的收入最低。

我还发现最低的平均收入水平低得可疑,在马萨诸塞州阿默斯特大学城社区中为2500美元,那里的每月平均住房成本为1215美元。 我的猜测是这是学生住房的集中地带,因此我排除了家庭收入中位数低于5,000美元的任何邮政编码。

这是创建这两个数据帧的代码:

zip_highest_income_row <- reactive({  filter(mydata(), MedianHouseholdIncome == max(MedianHouseholdIncome, na.rm = TRUE))})zip_lowest_income_row <- reactive({  filter(mydata(), MedianHouseholdIncome >= 5000) %>%  filter(MedianHouseholdIncome == min(MedianHouseholdIncome, na.rm = TRUE))})

这应该看起来像典型的dplyr filter()代码,不同之处在于1)每个都包装在dplyr filter() reactive({ })函数中,并且2)根据用户输入而变化的mydata动态数据帧称为mydata()而不是只是mydata

为了显示zip_highest_income_row数据框的ZIP列中第一项的值,我不能使用常规的R代码,例如zip_highest_income_row$Zip[1] 。 相反,我需要用括号引用动态数据框: zip_highest_income_row()$Zip[1] 。 然后将其包装在Shiny render()函数中,在本例中为renderText():

ZIP code `r renderText(zip_highest_income_row()$ZipCode[1])` in `r renderText(zip_highest_income_row()$City[1])` has the highest median income in the place(s) you selected, `r renderText(scales::dollar(zip_highest_income_row()$MedianHouseholdIncome[1]))`. 
ZIP code `r renderText(zip_lowest_income_row()$ZipCode[1])` in`r renderText(zip_lowest_income_row()$City[1])` has the lowest median income in the place(s) you selected,`r renderText(scales::dollar(zip_lowest_income_row()$MedianHouseholdIncome[1]))`.

运行并分享您的闪亮应用

一旦您添加了runtime: shiny R Markdown runtime: shiny ,它就不再是HTML文件了,而是一个迷你的Shiny应用程序。 这意味着它需要一个Shiny服务器才能运行。

正如我前面提到的,任何使用R,RStudio和Shiny软件包的人在其本地系统上都具有Shiny服务器。 这样可以轻松与R的其他用户共享任何Shiny应用程序。 您可以通过电子邮件向他们发送文档,或者更优雅地将其作为压缩文件在线发布,并使用shiny::runUrl()命令。 GitHub上的应用程序具有特殊的runGitHub()runGist()函数,如果您将GitHub用于项目,这些函数很方便,它们会自动将项目中的其他文件(例如数据文件)压缩。

但是有机会在某个时候向非R用户展示您的作品,这需要一个可公开访问的Shiny服务器。 最简单的选择可能是RStudio的shinyapps.io服务。 对于使用率非常低的一些有限的公共应用程序,它是免费的。 付费帐户的价格取决于它们为您的应用程序提供的活动时间。 活动时间用于衡量应用程序被有效使用的时间,一个小时一个小时与一个小时中的100个人处于同一小时。 为了确保几个应用程序的24x7全天候正常运行,您需要使用2,000美元/年的标准帐户(每年$ 1,100)。

您还可以在诸如AWS的云服务和R的安装以及RStudio的Shiny服务器软件的免费版本上构建自己的Shiny服务器 。 Dean Attali有一个很棒的分步教程,展示了如何在Digital Ocean上做到这一点,您可以在每月仅需$ 5托管成本的情况下构建和运行小型Shiny服务器,而不必担心活动时间。 权衡是您自己进行补丁和R /库更新-对于健壮的应用程序,您可能需要比最便宜的1G Droplet更强大的虚拟服务器。

添加交互式地图

最后,我将指导您如何使用传单包向该文档添加交互式地图。

首先,您需要一个包含地理空间数据和数字数据的文件,因此您的应用程序知道每个邮政编码的形状。 以下代码说明了如何使用tidycensus和sf包创建空间数据框。

为了实现交互性,我将创建该空间数据的动态版本,因此只有选定的城市才会显示在地图上。 下面是我这样做的代码。 它可能看起来有些重复,但是我要讲的是可读性而不是简洁。 随意收紧自己的版本。

mapdata <- reactive({  if("All Mass" %in% input$mycities){    ma_appdata_for_map %>%      dplyr::select(ZipCode = GEOID, MedianHouseholdIncome = medincome, MedianMonthlyHousingCost = medmonthlyhousingcost, Population = pop, City, County = county.name, State, Lat, Long, income, housing, Pop, geometry) %>%      mutate(        Highlighted = "Yes"      ) %>%      sf::st_as_sf()  } else {  dplyr::filter(ma_appdata_for_map, City %in% input$mycities) %>%  dplyr::select(ZipCode = GEOID, MedianHouseholdIncome = medincome, MedianMonthlyHousingCost = medmonthlyhousingcost, Population = pop, City, County = county.name, State, Lat, Long, income, housing, Pop, geometry) %>%  dplyr::mutate(    Highlighted = ifelse(City %in% input$mycities, "Yes", "No")  ) %>%    sf::st_as_sf()  }})

React功能现在应该很熟悉。 我的ifelse陈述考虑了用户是选择“全部大众”还是仅选择了单个城市。 除了“全部质量”之外,任何其他选择都只针对选定的城市进行过滤。 在这两种情况下,我都使用常规的dplyr select()函数选择要在地图中显示的列,并确保包括纬度的纬度,经度的纬度以及包含邮政编码多边形形状文件的几何图形。 每个if()代码部分的最后一行确保结果是一个sf(简单要素)地理空间对象。 虽然我不需要在本地Mac上使用该代码,但将其包含在应用程序中时,该应用程序在shinyapps.io上的运行效果更好。

现在是时候处理地图颜色了。 我将为传单地图设置两个React性调色板,一个用于收入,另一个用于住房成本。 在两种情况下,我都使用果岭,但是您可以选择任何果岭。

incomepal <- reactive({  leaflet::colorNumeric(palette = "Greens",     domain = mapdata()$MedianHouseholdIncome)})housingpal <- reactive({  leaflet::colorNumeric(palette = "Greens",     domain = mapdata()$MedianMonthlyHousingCost)})

我也希望它们是被动的,因此它们会根据用户的选择进行更改。 domain参数定义了调色板将显示的值。 在第一种情况下,它是我的React式mapdata对象的MedianHouseholdIncome列,因为它是React性的,所以mapdata编码为mapdata() 。 在第二种情况下,它是MedianMonthlyHousingCost列。

我还将完全设置我希望我的弹出文本出现的方式。 这可能需要混合使用HTML( <br />是HTML换行符)和数据框列。 虽然您当然可以使用基本R的paste()paste0()函数,但是当处理多个与文本混合在一起的变量时,我发现胶水包装更加容易。 您可以在下面看到,我只需要将要求值的变量括在花括号内。 当然,弹出文本也需要是React性的,因此它也随用户的选择而变化。

mypopups <- reactive({  glue::glue("ZIP Code: {mapdata()$ZipCode}<br />Median Household Income: {mapdata()$income}<br />Median Monthly Housing Cost: {mapdata()$housing}<br />Population: {mapdata()$Pop}<br />City: {mapdata()$City}<br />County: {mapdata()$County}")})

最后,为传单地图本身编写代码。

leaflet::renderLeaflet({  leaflet(mapdata()) %>%   addProviderTiles("CartoDB.Positron") %>%    addPolygons(fillColor = ~incomepal()(mapdata()$MedianHouseholdIncome),              fillOpacity = 0.7,               weight = 1.0,               color = "black",              smoothFactor = 0.2,              popup = mypopups(),              group = "Household Income"  ) %>%      addPolygons(fillColor = ~housingpal()(mapdata()$MedianMonthlyHousingCost),              fillOpacity = 0.7,               weight = 0.2,               color = "black",              smoothFactor = 0.2,              popup = mypopups(),              group = "Housing Costs"  ) %>%  addLayersControl(      baseGroups=c("Household Income", "Housing Costs"),      position = "bottomleft",      options = layersControlOptions(collapsed = FALSE)      ) })

renderLeaflet()是Shiny渲染函数,它将依赖于动态mapdata对象显示动态dataviz。 该函数内部是“常规”传单映射代码。 第一行leaflet(mapdata())从React性mapdata对象创建一个R传单对象。 它使用的是leaflet包,它是leaflet.js库的R包装器。 下一行添加了来自CartoDB的背景地图图块样式 。

addPolygons()函数告诉传单如何显示邮政编码的多边形。 我希望它使用我之前设置的收入调色板“ incinepal”在MideanHouseholdIncome列中进行着色。 这些论点的其余大部分都是样式。 popup参数将弹出文本设置为我先前创建的mypopups对象,而group参数为地图图层命名。

我为月住房中位数添加了另一个类似的层。 最后, addLayersControl()addLayersControl()为每个图层放置一个可单击的图例。

Sharon Machlis / IDG

使用用于Leaflet.js和CartoDB背景图块的R 传单包包装器的传单地图。

如果您想了解有关使用传单在R中进行映射的更多信息,请参阅我的教程“ 用10个(相当简单的步骤)在R中创建地图 ”。

最终的R降价文件

您可以在GitHub上看到最终的R Markdown文件 。 如果仔细看一下代码,可能会发现一些补充。 我已将All Mass添加到selectInput()下拉列表选择向量中,因此现在的代码是

selectInput("mycities", "Choose 1 or more cities: ",choices = c("All Mass", sort(unique(markdowndata$City))), multiple = TRUE, selected = "Boston")

然后,如果选择了“全部质量”,我将对其他几行代码进行调整,以提供不同的选项,例如创建一个动态变量selected_places,如果“全部质量”是所选城市之一,则将显示“ Massachusetts”。

selected_places <- reactive({  if("All Mass" %in% input$mycities){  "Massachusetts"} else {  paste(input$mycities,   sep = " ", collapse = ", ")}})

另请注意新的YAML标头:

---title: "Median Household Income by ZIP Code"output: html_documentresource_files:   - mamarkdowndata.rdata   - zip_mass_appdata_for_map.rdsruntime: shiny---

resources_files: option表示该文档需要两个其他文件才能运行: mamarkdowndata.rdatazip_mass_appdata_for_map.rds 。 这样,当使用rsconnect::deployDoc("docname.Rmd")部署文件时,shinyapps.io便知道这些文件需要与R Markdown主文档一起上传。

您可以在https://idgrapps.shinyapps.io/runtimeshiny/上看到带有Shiny的交互式R Markdown文档。 加载可能需要一点时间,因为我没有尝试针对速度优化此代码。 RStudio有一些资源,如果您想了解加速Shiny应用程序的知识 。

这与“真实的” Shiny应用有什么不同?

这款带有Shiny R Markdown超级功能的文档在一些关键方面与功能完善的Shiny应用程序有所不同。

1.一个闪亮的应用程序必须位于一个名为app.R的文件中,或者位于两个文件ui.R和server.R中。 该应用程序可以与其他名称的其他文件,但文件命名结构是绝对的。 在单文件app.R应用程序中,ui(用户界面,定义用户看到并与之交互的内容)和服务器需要一些部分。

2.闪亮的应用程序布局围绕Bootstrap页面网格框架构建。 您可以在RStudio的Shiny应用程序布局指南中了解有关布局结构的更多信息。

3.您要呈现的大多数动态组件(包括图形和表格)都需要专门放置在页面上的其他输出功能和定义中。 例如,除了服务器代码leafletOutput("mymap")例如)之外,交互式传单地图还需要在ui的某个位置使用诸如leafletOutput("mymap")代码来告知应用程序应在何处显示。

output$mymap <- renderLeaflet({ #MAP CODE HERE })

定义生成地图背后的逻辑。

这是此应用的直方图和表格的Shiny app.R文件的示例:

library("shiny")library("dplyr")library("ggplot2")library("DT")options(scipen = 999)load("mamarkdowndata.rdata") # loads variable markdowndatama_appdata_for_map <- readRDS("zip_mass_appdata_for_map.rds")# Define UI ui <- fluidPage(    # Application title    titlePanel("Income and Housing Costs by ZIP Code"),    # Sidebar     sidebarLayout(        sidebarPanel(        selectInput("mycities", "Choose 1 or more Massachusetts places: ", choices = c("All Mass", sort(unique(markdowndata$City))), multiple = TRUE, selected = "Boston"),        br(),        strong("Note: some cities may have more than one place name for ZIP codes. For example, Allston, Brighton, Dorchester, and several other neighborhoods are not included in ZIP code place name \"Boston\".")        ),        # Show histogram        mainPanel(           h4(htmlOutput("histogramHeadline")),           plotOutput("myhistogram"),           br(),           h4(htmlOutput("tableHeadline")),           DTOutput("mytable")        )    ))# Define server logic required to draw a histogramserver <- function(input, output) {    mydata <- reactive({        if("All Mass" %in% input$mycities){            markdowndata        } else {            filter(markdowndata, City %in% input$mycities)        }    })    selected_places <- reactive({        if("All Mass" %in% input$mycities){            "Massachusetts"        } else {            paste(input$mycities,                   sep = " ", collapse = ", ")        }    })    output$histogramHeadline <- renderUI({        paste("Histogram for", selected_places(), " income data")    })    output$tableHeadline <- renderUI({        paste("Data for", selected_places())    })    output$myhistogram <- renderPlot({        ggplot(mydata(), aes(x = MedianHouseholdIncome)) +            geom_histogram(binwidth = 20000, color = "black", fill = "darkgreen") +            theme_classic() +            xlab("") +            ylab("")  +            scale_x_continuous(labels = dollar)})   output$mytable <- renderDT({       DT::datatable(mydata(), filter = 'top') %>%           formatCurrency(4:5, digits = 0) %>%           formatCurrency(6, currency = "", digits = 0)   })}# Run the application shinyApp(ui = ui, server = server)

您可以在RStudio的Shiny入门教程中找到有关构建此类Shiny应用程序的更多信息。

有关更多R技巧,请访问InfoWorld上的“用R做更多” 视频页面或YouTube上的“用R做更多信息”播放列表 。

翻译自: https://www.infoworld.com/article/3391381/turn-an-r-markdown-document-into-an-interactive-experience.html

将R Markdown文档变成互动体验相关推荐

  1. Python 实现将 Markdown 文档转换为 EPUB 电子书文件

    Python 实现将 Markdown 文档转换为 EPUB 电子书文件 Markdown Markdown 是一种轻量级的标记语言,用于以简单且易于阅读的方式格式化文本.它由 John Gruber ...

  2. typora插入代码设置_一篇文章教会你如何在Markdown文档中插入数学公式

    我平时用的比较多的是Typora这个markdown编辑器.所以在这里就以Typora为例,介绍如何在Markdown文档中插入数学公式的方法. 如果你学会了这个方法,那么你无论使用哪一个markdo ...

  3. python下载图片到文件夹_python实现解析markdown文档中的图片,并且保存到本地~

    背景 前阵子简书好像说是凉了,搞得我有点小慌,毕竟我的大部分博客都是放在简书上面的,虽然简书提供了打包导出功能,但是只能导出文字,图片的话还是存在简书服务器上面,再加上我一直想要重新做一个个人博客,于 ...

  4. 工具:语雀导出MarkDown文档后图片修复

    微信公众号:乌鸦安全 扫取二维码获取更多信息!  01  描述 在比较早的时候,我比较纠结记笔记的产品,最初的时候是在使用Typora在本地写Markdown文档,后来试用了一下印象笔记,但是它的缺点 ...

  5. Markdown文档生成流程图、时序图、类图、状态图、ER图、用户旅程图、甘特图、饼图等

    简介 流程图.时序图.类图.状态图.ER图.用户旅程图.甘特图.饼图等这些图都可以以文本的形式插入到Markdown文档中,使用一种叫mermaid的语法. 是一种用文本描述图形的方法. 下面的代码, ...

  6. html文件hexo博客,使用小书匠写 MarkDown 文档 Hexo 博客

    小书匠是一个功(zhong)能(liang)强(ji)大的 MarkDown 文档编辑器,除了支持常规的 MarkDown 语法,还要很多扩展语法(代码高亮 ,gfm ,脚注 ,上标 ,下标 ,文字高 ...

  7. 在HBuilder中编辑markdown文档(原)

    最近才真正意识到markdown的神奇.本篇内容主要部分来自HBuilderX自带的markdown语法帮助,加入了一些自己认为很实用的使用方法. 目 录 自动生成目录 返回目录 生成html页面 引 ...

  8. MarkdownView:Markdown 文档预览视图组件

    原文链接:https://github.com/keitaoouchi/MarkdownView MarkdownView:Markdown 文档预览视图组件.# 为开源点赞# -- 由SwiftLa ...

  9. idea中的markdown文档如何插入图片

    一.情景说明   有些时候我们需要在我们的项目中写类似readme.md文档,聪明的你知道怎么在该文档中插入本项目中的图片? 二.markdown中插入本地图片 插入网络图片 ![github](ht ...

  10. linux 如何查看终端格式,你应该还不知道,Linux终端下的 Markdown 文档查看器

    原标题:你应该还不知道,Linux终端下的 Markdown 文档查看器 现在,Markdown 差不多已经成为技术文档的标准.它可以实现技术文档的快捷写作,以及输出发布.同样都是标记语言,但Mark ...

最新文章

  1. 【LeetCode】55.跳跃游戏
  2. 依赖注入(DI)和Ninject,Ninject
  3. taro引入f2图表_Package - taro-f2
  4. 编译小米android系统软件,为Android加入busybox工具之小米(开发版本)
  5. ActionScript3(AS3)类库学习之(八)——自定义上下文菜单
  6. 三因素三水平正交表l9_影响多腔导管挤出机头设计的关键因素
  7. [CareerCup] 4.4 Create List at Each Depth of Binary Tree 二叉树的各层创建链表
  8. 性能测试:基础(2)
  9. 【收藏】机器学习与深度学习核心知识点总结
  10. x5webview TbsReaderView首次加载失败
  11. 减小pdf大小 打印 低分辨率
  12. 死磕Mosek!新mosek学习笔记1:VS项目配置。
  13. Linux rm过滤后的目录6,Linux 常用命令总结(一)
  14. 计算机毕业设计ssm龙腾集团员工信息管理系统39r5l系统+程序+源码+lw+远程部署
  15. python读二进制文件
  16. 旷厂练习生 Vol.16 | 两次进入研究院里的“研究院”实习是种什么体验?
  17. 搭建FTP服务器后访问时出现“FTP文件夹错误 无法与服务器建立连接”的解决办法
  18. 选取网页内容后弹出提示框,类似于微博的快捷转发功能。
  19. 0x80070570文件或目录损坏且无法读取解决方法
  20. nvme协议阅读笔记

热门文章

  1. 易语言短信接口_易语言短信接口_易语言发短信_易语言短信验证码_验证码短信代码示例_互亿无线...
  2. 分析微信小程序生成二维码接口报错41030: invalid page hint
  3. windows环境如何测试端口
  4. SSD固态硬盘知识简介
  5. IDEA安装阿里代码规范插件
  6. 【adb命令】电脑操作手机adb命令大全
  7. 【考研】2021年哈尔滨工业大学计算机考研「复试」经验贴
  8. 主成分分析——SPSS实操
  9. 实训报告万能模板计算机专业,计算机实训报告模板
  10. OMAPL138 DSP程序固化