İçeriği Python'da Word DOCX belgelerinden ayıklayın

Word belgelerinden metin çıkarma genellikle farklı senaryolarda gerçekleştirilir. Örneğin, metni analiz etmek, bir belgenin belirli bölümlerini çıkarmak ve bunları tek bir belgede birleştirmek vb. Bu makalede, Python’da programlı olarak Word belgelerinden metin çıkarmayı öğreneceksiniz. Ayrıca, içeriğin paragraflar, tablolar vb. belirli öğeler arasında dinamik olarak nasıl çıkarılacağını ele alacağız.

Word Belgelerinden Metin Çıkarmak için Python Kitaplığı

Aspose.Words for Python, MS Word belgelerini sıfırdan oluşturmanıza olanak tanıyan güçlü bir kitaplıktır. Ayrıca, mevcut Word belgelerini şifreleme, dönüştürme, metin çıkarma vb. için değiştirmenize olanak tanır. Bu kitaplığı, Word DOCX veya DOC belgelerinden metin çıkarmak için kullanacağız. Aşağıdaki pip komutunu kullanarak PyPI kütüphanesini kurabilirsiniz.

pip install aspose-words

Python Kullanarak Word Belgelerinde Metin Çıkarma

Bir MS Word belgesi, paragraflar, tablolar, resimler vb. içeren çeşitli öğelerden oluşur. Bu nedenle, metin çıkarma gereksinimleri bir senaryodan diğerine değişebilir. Örneğin, paragraflar, yer imleri, yorumlar vb. arasında metin ayıklamanız gerekebilir.

Bir Word belgesindeki her öğe türü bir düğüm olarak temsil edilir. Bu nedenle, bir belgeyi işlemek için düğümlerle oynamanız gerekecek. Öyleyse başlayalım ve farklı senaryolarda Word belgelerinden nasıl metin çıkarılacağını görelim.

Python’da bir Word Belgesinden Metin Çıkarma

Bu bölümde, Word belgeleri için bir Python metin çıkarıcı uygulayacağız ve metin çıkarmanın iş akışı aşağıdaki gibi olacaktır:

  • İlk olarak, metin çıkarma işlemine dahil etmek istediğimiz düğümleri tanımlayacağız.
  • Ardından, belirtilen düğümler arasındaki içeriği çıkaracağız (başlangıç ve bitiş düğümleri dahil veya hariç).
  • Son olarak, örneğin çıkarılan içerikten oluşan yeni bir Word belgesi oluşturmak için çıkarılan düğümlerin klonunu kullanacağız.

Şimdi, metin çıkarımını gerçekleştirmek için düğümleri ve diğer bazı parametreleri geçireceğimiz, extractcontent adında bir metot yazalım. Bu yöntem belgeyi ayrıştırır ve düğümleri klonlar. Bu metoda ileteceğimiz parametreler aşağıdadır.

  1. İçeriğin çıkarılması için sırasıyla başlangıç ve bitiş noktaları olarak StartNode ve EndNode. Bunlar hem blok düzeyinde (Paragraf , Tablo) hem de satır içi düzeyde (örn. Çalıştır, FieldStart, BookmarkStart vb.) düğümler olabilir.
    1. Bir alanı geçmek için ilgili FieldStart nesnesini geçmelisiniz.
    2. Yer imlerini geçirmek için BookmarkStart ve BookmarkEnd düğümleri geçilmelidir.
    3. Yorumlar için, CommentRangeStart ve CommentRangeEnd düğümleri kullanılmalıdır.
  2. IsInclusive, belirteçlerin ayıklamaya dahil edilip edilmediğini tanımlar. Bu seçenek false olarak ayarlanırsa ve aynı düğüm veya ardışık düğümler geçirilirse boş bir liste döndürülür.

Aşağıda, iletilen düğümler arasındaki içeriği çıkaran özüt içeriği yönteminin tam uygulaması yer almaktadır.

def extract_content(startNode : aw.Node, endNode : aw.Node, isInclusive : bool):
    
    # İlk önce, bu yönteme geçirilen düğümlerin kullanım için geçerli olup olmadığını kontrol edin.
    verify_parameter_nodes(startNode, endNode)

    # Ayıklanan düğümleri depolamak için bir liste oluşturun.
    nodes = []

    # İşaretçilerden biri, yorumun kendisi de dahil olmak üzere bir yorumun parçasıysa, işaretçiyi hareket ettirmemiz gerekir.
    # CommentRangeEnd düğümünden sonra bulunan Yorum Düğümüne iletin.
    if (endNode.node_type == aw.NodeType.COMMENT_RANGE_END and isInclusive) :
        
        node = find_next_node(aw.NodeType.COMMENT, endNode.next_sibling)
        if (node != None) :
            endNode = node

    # Gerekirse işaret düğümlerini ayırmak için bu yönteme geçirilen orijinal düğümlerin kaydını tutun.
    originalStartNode = startNode
    originalEndNode = endNode

    # Blok düzeyindeki düğümlere (paragraflar ve tablolar) dayalı olarak içeriği ayıklayın. Onları bulmak için üst düğümler arasında dolaşın.
    # İşaretçi düğümlerin satır içi olup olmadığına bağlı olarak ilk ve son düğümlerin içeriğini böleceğiz.
    startNode = get_ancestor_in_body(startNode)
    endNode = get_ancestor_in_body(endNode)

    isExtracting = True
    isStartingNode = True
    # Belgeden çıkardığımız geçerli düğüm.
    currNode = startNode

    # İçeriği çıkarmaya başlayın. Tüm blok seviyesindeki düğümleri işleyin ve özellikle ilkini ayırın
    # ve gerektiğinde son düğümler, böylece paragraf biçimlendirmesi korunur.
    # Yöntem, çarpanlara ayırmamız gerektiğinden normal bir çıkarıcıdan biraz daha karmaşıktır.
    # kullanışlı hale getirmek için satır içi düğümleri, alanları, yer imlerini vb. kullanarak ayıklamada.
    while (isExtracting) :
        
        # Bir kopya elde etmek için geçerli düğümü ve alt öğelerini klonlayın.
        cloneNode = currNode.clone(True)
        isEndingNode = currNode == endNode

        if (isStartingNode or isEndingNode) :
            
            # Her işaretçiyi ayrı ayrı işlememiz gerekiyor, bu yüzden onu ayrı bir yönteme aktarın.
            # Düğüm dizinlerini tutmak için önce End işlenmelidir.
            if (isEndingNode) :
                # !isStartingNode: işaretçiler aynı düğüm ise düğümü iki kez eklemeyin.
                process_marker(cloneNode, nodes, originalEndNode, currNode, isInclusive, False, not isStartingNode, False)
                isExtracting = False

            # Koşullu, blok seviyesi başlangıç ve bitiş işaretçileri olarak ayrı, belki aynı düğümde olmalıdır.
            if (isStartingNode) :
                process_marker(cloneNode, nodes, originalStartNode, currNode, isInclusive, True, True, False)
                isStartingNode = False
            
        else :
            # Düğüm bir başlangıç veya bitiş işaretçisi değildir, kopyayı listeye eklemeniz yeterlidir.
            nodes.append(cloneNode)

        # Bir sonraki düğüme geçin ve ayıklayın. Bir sonraki düğüm Yok ise,
        # içeriğin geri kalanı farklı bir bölümde bulunur.
        if (currNode.next_sibling == None and isExtracting) :
            # Sonraki bölüme geçin.
            nextSection = currNode.get_ancestor(aw.NodeType.SECTION).next_sibling.as_section()
            currNode = nextSection.body.first_child
            
        else :
            # Vücuttaki bir sonraki düğüme git.
            currNode = currNode.next_sibling
            
    # Satır içi yer imlerine sahip modla uyumluluk için sonraki paragrafı ekleyin (boş).
    if (isInclusive and originalEndNode == endNode and not originalEndNode.is_composite) :
        include_next_paragraph(endNode, nodes)

    # Düğüm işaretçileri arasındaki düğümleri döndürün.
    return nodes

Metin çıkarma işlemini gerçekleştirmek için, özütleme yöntemi tarafından aşağıda verilen bazı yardımcı yöntemler de gereklidir.

def verify_parameter_nodes(start_node: aw.Node, end_node: aw.Node):

    # Bu kontrollerin yapılma sırası önemlidir.
    if start_node is None:
        raise ValueError("Start node cannot be None")
    if end_node is None:
        raise ValueError("End node cannot be None")

    if start_node.document != end_node.document:
        raise ValueError("Start node and end node must belong to the same document")

    if start_node.get_ancestor(aw.NodeType.BODY) is None or end_node.get_ancestor(aw.NodeType.BODY) is None:
        raise ValueError("Start node and end node must be a child or descendant of a body")

    # Bitiş düğümünün, DOM ağacındaki başlangıç düğümünden sonra olduğunu kontrol edin.
    # Önce farklı bölümlerde olup olmadığına bakın, sonra değilse,
    # aynı bölümün gövdesindeki konumlarını kontrol edin.
    start_section = start_node.get_ancestor(aw.NodeType.SECTION).as_section()
    end_section = end_node.get_ancestor(aw.NodeType.SECTION).as_section()

    start_index = start_section.parent_node.index_of(start_section)
    end_index = end_section.parent_node.index_of(end_section)

    if start_index == end_index:

        if (start_section.body.index_of(get_ancestor_in_body(start_node)) >
            end_section.body.index_of(get_ancestor_in_body(end_node))):
            raise ValueError("The end node must be after the start node in the body")

    elif start_index > end_index:
        raise ValueError("The section of end node must be after the section start node")

 
def find_next_node(node_type: aw.NodeType, from_node: aw.Node):

    if from_node is None or from_node.node_type == node_type:
        return from_node

    if from_node.is_composite:

        node = find_next_node(node_type, from_node.as_composite_node().first_child)
        if node is not None:
            return node

    return find_next_node(node_type, from_node.next_sibling)

 
def is_inline(node: aw.Node):

    # Düğümün bir Paragraf veya Tablo düğümünün alt öğesi olup olmadığını ve bir paragraf olmadığını test edin
    # veya bir paragrafa uygun bir yorum sınıfı içinde bir tablo bir paragraf mümkündür.
    return ((node.get_ancestor(aw.NodeType.PARAGRAPH) is not None or node.get_ancestor(aw.NodeType.TABLE) is not None) and
            not (node.node_type == aw.NodeType.PARAGRAPH or node.node_type == aw.NodeType.TABLE))

 
def process_marker(clone_node: aw.Node, nodes, node: aw.Node, block_level_ancestor: aw.Node,
    is_inclusive: bool, is_start_marker: bool, can_add: bool, force_add: bool):

    # Blok düzeyinde bir düğümle uğraşıyorsak, dahil edilmesi gerekip gerekmediğine bakın ve listeye ekleyin.
    if node == block_level_ancestor:
        if can_add and is_inclusive:
            nodes.append(clone_node)
        return

    # cloneNode, blockLevelNode'un bir klonudur. Düğüm != blockLevelNode ise, blockLevelAncestor
    # düğümün atası, yani bileşik bir düğümdür.
    assert clone_node.is_composite

    # Bir işaretçi bir FieldStart düğümüyse, dahil edilip edilmeyeceğini kontrol edin.
    # Basit olması için FieldStart ve FieldEnd'in aynı paragrafta göründüğünü varsayıyoruz.
    if node.node_type == aw.NodeType.FIELD_START:
        # İşaretçi bir başlangıç düğümüyse ve dahil edilmemişse, alanın sonuna atlayın.
        # İşaretçi bir bitiş düğümüyse ve dahil edilecekse, alanın kaldırılmaması için bitiş alanına gidin.
        if is_start_marker and not is_inclusive or not is_start_marker and is_inclusive:
            while node.next_sibling is not None and node.node_type != aw.NodeType.FIELD_END:
                node = node.next_sibling

    # İşaretçi düğümü, belge gövdesinin üçüncü düzeyinde veya altındaysa, bir servis talebini destekleyin.
    node_branch = fill_self_and_parents(node, block_level_ancestor)

    # Klonlanmış düğümümüzde ilgili düğümü dizine göre işleyin.
    current_clone_node = clone_node
   for i in range(len(node_branch) - 1, -1):

        current_node = node_branch[i]
        node_index = current_node.parent_node.index_of(current_node)
        current_clone_node = current_clone_node.as_composite_node.child_nodes[node_index]

        remove_nodes_outside_of_range(current_clone_node, is_inclusive or (i > 0), is_start_marker)

    # İşlemden sonra, bileşik düğüm, içermiyorsa boş olabilir.
    if can_add and (force_add or clone_node.as_composite_node().has_child_nodes):
        nodes.append(clone_node)

 
def remove_nodes_outside_of_range(marker_node: aw.Node, is_inclusive: bool, is_start_marker: bool):

    is_processing = True
    is_removing = is_start_marker
    next_node = marker_node.parent_node.first_child

    while is_processing and next_node is not None:

        current_node = next_node
        is_skip = False

        if current_node == marker_node:
            if is_start_marker:
                is_processing = False
                if is_inclusive:
                    is_removing = False
            else:
                is_removing = True
                if is_inclusive:
                    is_skip = True

        next_node = next_node.next_sibling
        if is_removing and not is_skip:
            current_node.remove()

 
def fill_self_and_parents(node: aw.Node, till_node: aw.Node):

    nodes = []
    current_node = node

    while current_node != till_node:
        nodes.append(current_node)
        current_node = current_node.parent_node

    return nodes

 
def include_next_paragraph(node: aw.Node, nodes):

    paragraph = find_next_node(aw.NodeType.PARAGRAPH, node.next_sibling).as_paragraph()
    if paragraph is not None:

        # İçeriksiz paragraflar eklemek için ilk alt öğeye gidin.
        marker_node = paragraph.first_child if paragraph.has_child_nodes else paragraph
        root_node = get_ancestor_in_body(paragraph)

        process_marker(root_node.clone(True), nodes, marker_node, root_node,
            marker_node == paragraph, False, True, True)

 
def get_ancestor_in_body(start_node: aw.Node):

    while start_node.parent_node.node_type != aw.NodeType.BODY:
        start_node = start_node.parent_node
    return start_node
def generate_document(src_doc: aw.Document, nodes):

    dst_doc = aw.Document()
    # İlk paragrafı boş belgeden çıkarın.
    dst_doc.first_section.body.remove_all_children()

    # Listedeki her düğümü yeni belgeye aktarın. Düğümün orijinal biçimlendirmesini koruyun.
    importer = aw.NodeImporter(src_doc, dst_doc, aw.ImportFormatMode.KEEP_SOURCE_FORMATTING)

   for node in nodes:
        import_node = importer.import_node(node, True)
        dst_doc.first_section.body.append_child(import_node)

    return dst_doc

 
def paragraphs_by_style_name(doc: aw.Document, style_name: str):

    paragraphs_with_style = []
    paragraphs = doc.get_child_nodes(aw.NodeType.PARAGRAPH, True)

   for paragraph in paragraphs:
        paragraph = paragraph.as_paragraph()
        if paragraph.paragraph_format.style.name == style_name:
            paragraphs_with_style.append(paragraph)

    return paragraphs_with_style

Artık bu yöntemleri kullanmaya ve bir Word belgesinden metin çıkarmaya hazırız.

Bir Word Belgesindeki Paragraflar Arasındaki Metni Çıkarma

Bir Word DOCX belgesinde iki paragraf arasındaki içeriğin nasıl çıkarılacağını görelim. Python’da bu işlemi gerçekleştirmenin adımları aşağıdadır.

  • İlk olarak, Document sınıfını kullanarak Word belgesini yükleyin.
  • Document.firstsection.body.getchild(NodeType.PARAGRAPH, int, boolean).asparagraph() yöntemini kullanarak başlangıç ve bitiş paragraflarının referansını iki nesneye alın.
  • Düğümleri bir nesneye ayıklamak için extractcontent(startPara, endPara, True) yöntemini çağırın.
  • Ayıklanan içerikten oluşan belge oluşturmak için generatorocument(Document, extractedNodes) yardımcı yöntemini çağırın.
  • Son olarak, Document.save(string) yöntemini kullanarak döndürülen belgeyi kaydedin.

Aşağıdaki kod örneği, Python’da bir Word belgesinde 7. ve 11. paragraflar arasındaki metnin nasıl çıkarılacağını gösterir.

# Belgeyi yükleyin.
doc = aw.Document("Extract content.docx")

# Başlangıç ve bitiş paragraflarını tanımlayın.
startPara = doc.first_section.body.get_child(aw.NodeType.PARAGRAPH, 6, True).as_paragraph()
endPara = doc.first_section.body.get_child(aw.NodeType.PARAGRAPH, 10, True).as_paragraph()

# Belgedeki bu paragraflar arasındaki içeriği çıkarın. Bu işaretleri ekstraksiyona dahil edin.
extractedNodes = extract_content(startPara, endPara, True)

# Ayıklanan içeriği içeren belge oluşturun.
dstDoc = generate_document(doc, extractedNodes)

# Belgeyi kaydedin.
dstDoc.save("extract_content_between_paragraphs.docx")

Bir Word Belgesinde Farklı Düğüm Türleri Arasında Metin Çıkarma

Farklı düğüm türleri arasında da içerik çıkarabilirsiniz. Gösterim için, bir paragraf ve bir tablo arasındaki içeriği çıkaralım ve yeni bir Word belgesine kaydedelim. Aşağıda bu işlemi gerçekleştirmek için adımlar verilmiştir.

  • Document sınıfını kullanarak Word belgesini yükleyin.
  • Document.firstsection.body.getchild(NodeType, int, boolean) yöntemini kullanarak başlangıç ve bitiş düğümlerinin referansını iki nesneye alın.
  • Düğümleri bir nesneye ayıklamak için extractcontent(startPara, endPara, True) yöntemini çağırın.
  • Ayıklanan içerikten oluşan belge oluşturmak için generatorocument(Document, extractedNodes) yardımcı yöntemini çağırın.
  • Döndürülen belgeyi Document.save(string) yöntemini kullanarak kaydedin.

Aşağıdaki kod örneği, Python’da bir paragraf ile bir tablo arasındaki metnin nasıl ayıklanacağını gösterir.

# Belgeyi yükle
doc = aw.Document("Extract content.docx")

# Başlangıç ve bitiş düğümlerini tanımlayın.
start_para = doc.last_section.get_child(aw.NodeType.PARAGRAPH, 2, True).as_paragraph()
end_table = doc.last_section.get_child(aw.NodeType.TABLE, 0, True).as_table()

# Belgedeki bu düğümler arasındaki içeriği çıkarın. Bu işaretleri ekstraksiyona dahil edin.
extracted_nodes = extract_content(start_para, end_table, True)

# Ayıklanan içeriği içeren belge oluşturun.
dstDoc = generate_document(doc, extractedNodes)

# Belgeyi kaydedin.
dstDoc.save("extract_content_between_nodes.docx")

Stillere Göre Paragraflar Arasındaki Metni Çıkarın

Şimdi, stillere göre paragraflar arasında nasıl içerik çıkarılacağını kontrol edelim. Gösterim için, Word belgesindeki ilk “Başlık 1” ile ilk “Başlık 3” arasındaki içeriği çıkaracağız. Aşağıdaki adımlar Python’da bunun nasıl başarılacağını göstermektedir.

  • İlk olarak, Document sınıfını kullanarak Word belgesini yükleyin.
  • Ardından, paragrafları bystylename(Document, “Heading 1”) yardımcı yöntemini kullanarak bir nesneye çıkarın.
  • Paragraflar bystylename(Document, “Heading 3”) yardımcı yöntemini kullanarak başka bir nesneye çıkarın.
  • extractcontent(startPara, endPara, True) yöntemini çağırın ve her iki paragraf dizisindeki ilk öğeleri birinci ve ikinci parametreler olarak iletin.
  • Ayıklanan içerikten oluşan belge oluşturmak için generatorocument(Document, extractedNodes) yardımcı yöntemini çağırın.
  • Son olarak, Document.save(string) yöntemini kullanarak döndürülen belgeyi kaydedin.

Aşağıdaki kod örneği, stilleri temel alan paragraflar arasında içeriğin nasıl ayıklanacağını gösterir.

# Belgeyi yükle
doc = aw.Document("Extract content.docx")

# İlgili başlık stillerini kullanarak paragrafların bir listesini toplayın.
parasStyleHeading1 = paragraphs_by_style_name(doc, "Heading 1")
parasStyleHeading3 = paragraphs_by_style_name(doc, "Heading 3")

# Bu stillerle paragrafların ilk örneğini kullanın.
startPara1 = parasStyleHeading1[0]
endPara1 = parasStyleHeading3[0]

# Belgedeki bu düğümler arasındaki içeriği çıkarın. Bu işaretleri ekstraksiyona dahil etmeyin.
extractedNodes = extract_content(startPara1, endPara1, False)

# Ayıklanan içeriği içeren belge oluşturun.
dstDoc = generate_document(doc, extractedNodes)

# Belgeyi kaydedin.
dstDoc.save("extract_content_between_paragraphs_based_on-Styles.docx")

Devamını oku

Bu belgeleme makalesini kullanarak Word belgelerinden metin ayıklamanın diğer senaryolarını keşfedebilirsiniz.

Ücretsiz API Lisansı Alın

Aspose.Words for Python’u değerlendirme sınırlamaları olmadan kullanmak için bir geçici lisans alabilirsiniz.

Çözüm

Bu makalede, Python kullanarak MS Word belgelerinden nasıl metin çıkarılacağını öğrendiniz. Ayrıca, bir Word belgesindeki benzer veya farklı düğüm türleri arasında programlı olarak nasıl içerik çıkarılacağını gördünüz. Böylece Python’da kendi MS Word metin çıkarıcınızı oluşturabilirsiniz. Ayrıca, belgeleri kullanarak Aspose.Words for Python’un diğer özelliklerini keşfedebilirsiniz. Herhangi bir sorunuz olması durumunda forumumuz aracılığıyla bize bildirmekten çekinmeyin.

Ayrıca bakınız

Bilgi: Bir PowerPoint sunumundan bir Word belgesi almanız gerekirse, Aspose Sunumdan Word Belgesine dönüştürücü kullanabilirsiniz.