python-docx摸索:写一个主席令自动排版的爬虫

查看 39|回复 1
作者:txq0211   
闲来无事,储备点知识。
有时候帮别人从网页上复制一些国家法规,整下来按公文排版是个麻烦事。
Windows上还有各种插件,国产系统上可没啥辅助工具。
尝试着学习下python-docx,过程中遇到很多问题,懂得这个的大神麻烦指导下。
发文的格式复杂些,目前尚未解决问题较多,先上一个简单的国务院令的代码。
存在问题:



WX20230319-223908.png (102.39 KB, 下载次数: 0)
下载附件
2023-3-19 22:39 上传



[Python] 纯文本查看 复制代码                set_bold = re.findall('(?python-docx中,通过run修改文字,会导致整段的文字格式全部变化,退而求其次,
先分割再拼接完成了效果,方法有点笨,希望能有懂得大神指导下。
先上最终效果
源网站:


WX20230319-221501.png (166.33 KB, 下载次数: 0)
下载附件
2023-3-19 22:24 上传

测试效果:


WX20230319-221329.png (169.65 KB, 下载次数: 0)
下载附件
2023-3-19 22:25 上传



WX20230319-221354.png (251 KB, 下载次数: 0)
下载附件
2023-3-19 22:25 上传



WX20230319-221417.png (189.22 KB, 下载次数: 0)
下载附件
2023-3-19 22:25 上传

换一篇测试:



WX20230319-221616.png (263.73 KB, 下载次数: 0)
下载附件
2023-3-19 22:27 上传


完整代码:
[Python] 纯文本查看 复制代码import requests
from bs4 import BeautifulSoup
import re
from docx import Document
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT, WD_LINE_SPACING, WD_BREAK
from docx.oxml import OxmlElement
from docx.oxml.ns import qn
from docx.shared import Pt, Cm, RGBColor
# 常用中英文标点转换
def E_trans_to_C(string):
    E_pun = u',!?[]【】()'
    C_pun = u',!?〔〕〔〕()《》'
    table= {ord(f):ord(t) for f,t in zip(E_pun,C_pun)}
    return string.translate(table)
# 设置页面样式
def setDocument():
    # -----------文档部分设置-------------#
    document = Document()
    # 文档页面设置
    # A4和页边距
    document.sections[0].page_height = Cm(29.7)
    document.sections[0].page_width = Cm(22)
    document.sections[0].left_margin = Cm(2.8)
    document.sections[0].right_margin = Cm(2.6)
    document.sections[0].top_margin = Cm(2.5)
    document.sections[0].bottom_margin = Cm(2.5)
    return document
def AddFooterNumber(run):
    fldChar1 = OxmlElement('w:fldChar')  # creates a new element
    fldChar1.set(qn('w:fldCharType'), 'begin')  # sets attribute on element
    instrText = OxmlElement('w:instrText')
    instrText.set(qn('xml:space'), 'preserve')  # sets attribute on element
    instrText.text = 'Page'
    fldChar2 = OxmlElement('w:fldChar')
    fldChar2.set(qn('w:fldCharType'), 'separate')
    t = OxmlElement('w:t')
    t.text = "Seq"
    fldChar2.append(t)
    fldChar4 = OxmlElement('w:fldChar')
    fldChar4.set(qn('w:fldCharType'), 'end')
    r_element = run._r
    r_element.append(fldChar1)
    r_element.append(instrText)
    r_element.append(fldChar2)
    r_element.append(fldChar4)
def InsertPageNumber(Doc):
    footer = Doc.sections[0].footer  # 获取第一个节的页脚
    footer.is_linked_to_previous = True  # 编号续前一节
    paragraph = footer.paragraphs[0]  # 获取页脚的第一个段落
    paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER  # 页脚居中对齐
    run_footer = paragraph.add_run()  # 添加页脚内容
    AddFooterNumber(run_footer)
    run_footer.first_line_indent = Pt(-32)
    font = run_footer.font
    font.name = 'Times New Roman'  # 新罗马字体
    font.size = Pt(14)  # 14号字体
    font.bold = False  # 不加粗
# 设置正文样式
def setContent(content):
    content = document.add_paragraph(content)
    document.styles['Normal'].font.name = u'仿宋_GB2312'
    document.styles['Normal'].font.size = Pt(16)
    document.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), u'仿宋_GB2312') # 中文字体
    document.styles['Normal']._element.rPr.rFonts.set(qn('w:ascii'), u'Times New Roman') # 西文字体
    # document.styles['Normal'].paragraph_format.first_line_indent = document.styles['Normal'].font.size * 2
    document.styles['Normal'].paragraph_format.first_line_indent = Pt(32)
    document.styles['Normal'].paragraph_format.line_spacing_rule = WD_LINE_SPACING.EXACTLY  # 行距固定值
    document.styles['Normal'].paragraph_format.line_spacing = Pt(28) # 行距
    document.styles['Normal'].paragraph_format.space_after = Pt(0)
    document.styles['Normal'].paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.JUSTIFY  #LEFT,RIGHT,CENTER,JUSTIFY(两端对齐),DISTRIBUTE(分散对齐)
    return content
    # w:ascii -用于前128个Unicode代码点
    # w:cs -用于复杂的脚本代码点
    # w:eastAsia -用于东亚代码点
    # w:hAnsi -代表 高ANSI ,但实际上是对其他三个代码点之一未指定的所有代码点的捕获。
# 设置一级标题样式
def setHead1(head_1):
    head = document.add_heading()
    head.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 居中对齐
    head_1 = E_trans_to_C(head_1)
    run = head.add_run(head_1)
    run.font.name = u'方正小标宋简体'
    run._element.rPr.rFonts.set(qn('w:eastAsia'), u'方正小标宋简体')
    run._element.rPr.rFonts.set(qn('w:ascii'), u'Times New Roman')
    document.styles['Heading 1'].font.size = Pt(22) # 字体大小二号
    document.styles['Heading 1'].font.color.rgb=RGBColor(0x00,0x00,0x00) #标题颜色
    document.styles['Heading 1'].paragraph_format.first_line_indent = Pt(0) # 首行缩进
    document.styles['Heading 1'].paragraph_format.line_spacing = Pt(39)
    document.styles['Heading 1'].paragraph_format.space_before = Pt(0)
    document.styles['Heading 1'].paragraph_format.space_after = Pt(0)
    document.styles['Heading 1'].font.bold = False # 不加粗
    return run
# 设置文号样式
def setNumber(head_6):
    head = document.add_heading(level=6)
    head.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 居中对齐
    head_6 = E_trans_to_C(head_6)
    run = head.add_run(head_6)
    run.font.name = u'楷体_GB2312'
    run._element.rPr.rFonts.set(qn('w:eastAsia'), u'楷体_GB2312')
    run._element.rPr.rFonts.set(qn('w:ascii'), u'Times New Roman')
    document.styles['Heading 6'].font.size = Pt(16) # 字体大小二号
    document.styles['Heading 6'].font.color.rgb=RGBColor(0x00,0x00,0x00) #标题颜色
    document.styles['Heading 6'].paragraph_format.first_line_indent = Pt(0) # 首行缩进
    document.styles['Heading 6'].paragraph_format.line_spacing = Pt(28)
    document.styles['Heading 6'].paragraph_format.space_before = Pt(0)
    document.styles['Heading 6'].paragraph_format.space_after = Pt(0)
    document.styles['Heading 6'].font.italic = False # 倾斜
    document.styles['Heading 6'].font.bold = False # 加粗
    return run
# 设置二级标题样式
def setHead2(head_2):
    head = document.add_heading(level=2)
    head.paragraph_format.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER # 左对齐
    head_2 = E_trans_to_C(head_2)
    run = head.add_run(head_2)
    run.font.name = u'黑体'
    run._element.rPr.rFonts.set(qn('w:eastAsia'), u'黑体')
    run._element.rPr.rFonts.set(qn('w:ascii'), u'Times New Roman')
    document.styles['Heading 2'].font.size = Pt(16) # 字体三号
    document.styles['Heading 2'].font.color.rgb=RGBColor(0x00,0x00,0x00) #标题颜色
    document.styles['Heading 2'].paragraph_format.first_line_indent = 0
    document.styles['Heading 2'].paragraph_format.line_spacing = Pt(28)
    document.styles['Heading 2'].paragraph_format.space_before = Pt(0)
    document.styles['Heading 2'].paragraph_format.space_after = Pt(0)
    document.styles['Heading 2'].font.bold = False # 不加粗
    return run
if __name__ == '__main__':
    document = setDocument()
    footer = InsertPageNumber(document)
    url = 'http://www.gov.cn/zhengce/content/2021-07/22/content_5626534.htm'
    response = requests.get(url)
    response.encoding = response.apparent_encoding
    soup = BeautifulSoup(response.text, features="html.parser")  # 用html解析器(parser)来分析我们requests得到的html文字内容,soup就是我们解析出来的结果
    company_item = soup.find("td", class_="b12c")  # find是查找,find_all查找全部。查找标记名是div并且class属性是detail_head的全部元素
    title = soup.find("title").text.split('(')[0]
    news = company_item.text.strip() # strip() 方法用于移除字符串头尾指定的字符(默认为空格或换行符)或字符序列。在这里就是移除多余的尖括号的html数据
    # 使用.split('\n')或.splitlines()分割
    format_news = news.splitlines()
    # new = new.replace('\n','\r')
    Contents = {}
    for i in range(len(format_news)):
        # setHead1(format_news)
        set_head1 = re.findall('(?= len(format_news.encode()):
                rightIndent = ((len(format_news[i-1].encode()) - len(format_news.encode()))/2 + 4) * 8
                # print(rightIndent)
                Contents[i - 1].paragraph_format.right_indent = Pt(64)  # 右对齐
                Contents.paragraph_format.right_indent = Pt(rightIndent)  # 右对齐
            elif len(format_news[i-1].encode())

代码, 下载次数

xbb   

Python真好用,这样的功能也能实现,感谢楼主分享。
您需要登录后才可以回帖 登录 | 立即注册