1、插入超链接
在段落中插入超链接,目前python-docx没有提供现成的方法(截止到1.1.0版本),不像 add_run() 这么简单,没有add_hyperlink()这样的方法。我们可以自己封装一个add_hyperlink()方法用于在段落中插入超链接。
import docx
from docx.enum.dml import MSO_THEME_COLOR_INDEX
def add_hyperlink(paragraph, text, url):
# 获取paragraph的part对象,并且创建一个新的关系
part = paragraph.part
r_id = part.relate_to(url, docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK, is_external=True)
# 创建 w:hyperlink 标签并且添加所需的值
hyperlink = docx.oxml.shared.OxmlElement('w:hyperlink')
hyperlink.set(docx.oxml.shared.qn('r:id'), r_id, )
# 创建一个 w:r 元素 和一个 w:rPr 元素
new_run = docx.oxml.shared.OxmlElement('w:r')
rPr = docx.oxml.shared.OxmlElement('w:rPr')
# 把所有的 xml 元素合并到一起,并且添加显示的文本给 w:r 元素
new_run.append(rPr)
new_run.text = text
hyperlink.append(new_run)
# 创建一个新的 Run 对象并且添加新的超链接进去
r = paragraph.add_run()
r._r.append(hyperlink)
# 设置超链接的样式,样式颜色为超链接,并且文本有下划线
r.font.color.theme_color = MSO_THEME_COLOR_INDEX.HYPERLINK
r.font.underline = True
return hyperlink
document = docx.Document()
p = document.add_paragraph('这是一段话中的第一句,')
add_hyperlink(p, '跳转到baidu', 'https://www.baidu.com')
p.add_run(',这是第二句 ')
p2 = document.add_paragraph('这是第二段')
document.save('demo_hyperlink.docx')
运行效果如下:
2、获取超链接
直接读取 paragraph.text 或者 直接读取 run.text,都是无法获得超链接内容的,如下图。
因为超链接(hyperlink)是paragraph的一个子项,和Run是平级的。hyperlink本身包含Runs,超链接的文本存在Runs的text里。
2.1、获取超链接(包括文本和url)
# 2、获取超链接
import docx
from docx.enum.dml import MSO_THEME_COLOR_INDEX
from docx.opc.constants import RELATIONSHIP_TYPE as RT
def get_hyperlinks():
import re
d = docx.Document('demo_hyperlink.docx')
# 存放超链接URL
target = {}
# 存放超链接文本
text = {}
# 获取超链接
rels = d.part.rels
for rel in rels:
if rels[rel].reltype == RT.HYPERLINK:
id = rels[rel]._rId
target[id] = rels[rel]._target
# 获取超链接文本
for p in d.paragraphs:
# 将文档处理为xml,并转为字符串
xml = p.paragraph_format.element.xml
xml_str = str(xml)
# print(xml_str)
# 获取文本中由<w:hyperlink>标签包起来的部分
hl_list = re.findall('<w:hyperlink[\S\s]*?</w:hyperlink>', xml_str)
for hyperlink in hl_list:
# 获取rId
rid = re.search(r'r:id="(.*?)"', hyperlink).group(1)
# 获取文本中由<w:t>标签包起来的部分
wt_list = re.findall('<w:t[\S\s]*?</w:t>', hyperlink)
# print(wt_list)
temp = u''
for wt in wt_list:
# 去掉<w:t>标签
wt_content = re.sub('<[\S\s]*?>', u'', wt)
temp += wt_content
text[rid] = temp
results = []
for t in text.keys():
tmp_rel = { 'id':t, 'url':target[t],'text':text[t] }
results.append(tmp_rel)
# print(results)
return results
pass
运行结果:
2.2、获取超链接(仅文本)
# 获取超链接
d = docx.Document('demo_hyperlink.docx')
for p in d.paragraphs:
hls = p.hyperlinks
for hlink in hls:
for r in hlink.runs:
print(f'text:{r.text}')
3、修改超链接
3.1、修改超链接文本
def edit_hyperlink_text():
d = docx.Document('demo_hyperlink.docx')
# 1、根据指定的文本,修改为目标文本
origin_text = '示例一'
target_text = '示例二'
for p in d.paragraphs:
for hlink in p.hyperlinks:
# print(hlink.text)
if hlink.text == origin_text:
for r in hlink.runs:
r.clear()
hlink.runs[0].text = target_text
d.save('demo_hyperlink_1.docx')
原始文档如下:
代码运行后,“示例一” 修改为 “示例二”,效果如下:
3.2、修改超链接地址
def edit_hyperlink_url():
# 2、根据指定的文本,修改为目标url
origin_doc_name = 'demo_hyperlink_1.docx'
d = docx.Document(origin_doc_name)
hyperlinklist = get_hyperlinks(origin_doc_name)
print(hyperlinklist)
origin_text = '示例二'
target_url = 'https://www.qq.com'
ids = []
for hll in hyperlinklist:
if hll['text'] == origin_text:
print(rf"id={hll['id']}, url={hll['url']}, text={hll['text']}")
ids.append(hll['id'])
rels = d.part.rels
for rel in rels:
if rels[rel].reltype == RT.HYPERLINK:
id = rels[rel]._rId
if id in ids:
rels[rel]._target = target_url
print(rels[rel]._target)
d.save('demo_hyperlink_2.docx')
原始文档如下:
代码运行后,修改“示例二”的url地址为 www.qq.com,效果如下:
4、删除超链接
4.1、方法一:把超链接的内容置空
使用python-docx删除超链接时,由于无法删除run,所以可以使用一种变通的方式,即把超链接的文本置为空,达到删除超链接的效果。
def remove_hyperlink():
d = docx.Document('demo_hyperlink.docx')
# 删除超链接
origin_text = '示例一'
target_text = ''
for p in d.paragraphs:
for hlink in p.hyperlinks:
print(hlink.text)
if hlink.text == origin_text:
for r in hlink.runs:
r.clear()
hlink.runs[0].text = target_text
d.save('demo_hyperlink_1.docx')
原始文件内容:
代码运行后,删除 “示例一” 这个超链接,效果如下:
4.2、方法二:把超链接这个对象移除
第二种方法是把 Paragraph里的hyperlink对象移除
def remove_hyperlinks():
doc = docx.Document('demo_hyperlink.docx')
for paragraph in doc.paragraphs:
# 查找超链接
hyperlinks = [child for child in paragraph._element.getchildren() if child.tag.endswith('hyperlink')]
for hyperlink in hyperlinks:
# 删除超链接
paragraph._element.remove(hyperlink)
doc.save('demo_hyperlink_3.docx')
原始文件内容如下:
代码运行后效果如下:
5、取消超链接
用普通文本替换掉超链接,即把原文本上的超链接去除。
思路:
1、获取超链接的文本和url
2、移除超链接
3、插入文本
4、保存文档