Trích xuất dữ liệu từ tệp văn bản python

Trong bài viết này, tôi mô tả cách chuyển đổi một tập hợp các tệp văn bản thành một bảng dữ liệu có thể được sử dụng để xử lý ngôn ngữ tự nhiên và học máy. Để giới thiệu cách tiếp cận của mình, tôi sử dụng bộ dữ liệu thô của BBC News Article được xuất bản bởi D. Greene và P. Cickyham vào năm 2006

Trước khi nhảy vào IDE và bắt đầu viết mã, tôi thường tuân theo một quy trình bao gồm hiểu dữ liệu, xác định đầu ra và dịch mọi thứ thành mã. Tôi coi các nhiệm vụ trước khi viết mã thường là quan trọng nhất vì chúng giúp cấu trúc và tuân theo quy trình viết mã hiệu quả hơn

Quy trình ba bước của tôi cho dự án này1. Hiểu dữ liệu

Trước khi có thể trích xuất bất kỳ thông tin nào từ một tệp văn bản, chúng tôi muốn biết thông tin đó được cấu trúc như thế nào cũng như cách thức và vị trí các tệp văn bản được lưu trữ (e. g. tên, thư mục)

Cấu trúc

Để hiểu cấu trúc, chúng ta hãy xem một số tệp văn bản để hiểu cách dữ liệu được cấu trúc

Claxton hunting first major medal

British hurdler Sarah Claxton is confident she can win her first major medal at next month's European Indoor Championships in Madrid.

The 25-year-old has already smashed the British record over 60m hurdles twice this season, setting a new mark of 7.96 seconds to win the AAAs title. "I am quite confident," said Claxton. "But I take each race as it comes. "As long as I keep up my training but not do too much I think there is a chance of a medal." Claxton has won the national 60m hurdles title for the past three years but has struggled to translate her domestic success to the international stage.
...

Trong ngữ cảnh của các bài báo, có thể dễ dàng giả định rằng phần đầu tiên và phần thứ hai tương ứng với tiêu đề và phụ đề tương ứng. Các đoạn sau đây đại diện cho văn bản của bài báo. Nhìn vào dữ liệu mẫu, chúng tôi cũng nhận thấy rằng các phân đoạn được phân tách bằng các dòng mới có thể được sử dụng để chia văn bản

Kho

Để viết một tập lệnh tự động chạy qua mọi tệp văn bản, chúng ta cần biết các tệp văn bản được lưu trữ như thế nào. Vì vậy, chúng tôi quan tâm đến việc đặt tên và tổ chức các thư mục. Có khả năng, chúng tôi cần cơ cấu lại mọi thứ, để chúng tôi có thể lặp lại các tệp dễ dàng hơn

Đặt tên và tổ chức các tệp văn bản

May mắn cho chúng tôi, bộ dữ liệu tin tức của BBC đã được cấu trúc tốt để tự động trích xuất thông tin. Như có thể thấy trong ảnh chụp màn hình ở trên, các tệp văn bản được lưu trữ trong các thư mục theo thể loại của chúng. Tên cũng giống nhau cho mọi thể loại và được tạo bởi các số 0 đứng đầu (nếu số tệp dưới 100), số tệp và “. txt”

2. Định nghĩa đầu ra

Dựa trên những hiểu biết sâu sắc về bước hiểu dữ liệu, chúng ta có thể xác định thông tin nào sẽ được đưa vào đầu ra. Để xác định đầu ra, chúng ta phải xem xét các bài học của bước trước cũng như suy nghĩ về các trường hợp sử dụng tiềm năng cho đầu ra

Dựa trên thông tin mà chúng tôi có thể trích xuất từ ​​các tệp văn bản, tôi đưa ra hai trường hợp sử dụng khác nhau để đào tạo máy học

  • Phân loại văn bản (dự đoán thể loại dựa trên văn bản)
  • Tạo văn bản (tạo tiêu đề hoặc phụ đề dựa trên văn bản)

Để đáp ứng các yêu cầu cho cả hai trường hợp sử dụng tiềm năng, tôi khuyên bạn nên trích xuất thông tin sau

Extracting text files to gain informations about the genre, title, subtitle, text, and token count.

Đầu ra được nhắm mục tiêu để trích xuất thông tin tệp văn bản

Tôi cũng sẽ bao gồm độ dài của văn bản (theo số lượng mã thông báo), để dễ dàng lọc các văn bản ngắn hơn hoặc dài hơn sau này. Để lưu trữ dữ liệu được trích xuất, tôi sẽ đề xuất một giá trị được phân tách bằng tab (. tsv), vì có thể có dấu phẩy hoặc dấu chấm phẩy trong cột văn bản

3. mã hóa

Nhờ các bước trước, chúng tôi biết dữ liệu chúng tôi đang xử lý và loại thông tin nào chúng tôi muốn xuất ra khi kết thúc quá trình chuyển đổi. Như bạn có thể biết bây giờ, tôi muốn chia nhiệm vụ thành các phần nhỏ hơn. Bước mã hóa không tạo thành một ngoại lệ đối với điều này. ) Nói chung, tôi sẽ chia mã thành ít nhất ba phần khác nhau và bọc chúng trong các chức năng riêng lẻ

  • Đọc và tách một tập tin
  • Trích xuất thông tin
  • Xây dựng khung dữ liệu

Để làm cho trình trích xuất bài báo này có thể tái sử dụng, tôi tạo một lớp mới thực hiện các chức năng

Đọc và tách một tập tin

Để đọc một tệp bằng python, chúng ta cần đường dẫn tương ứng bao gồm thư mục và tên tệp. Như chúng ta đã quan sát trong bước Hiểu dữ liệu, các tệp được lưu trữ trong thư mục thể loại tương ứng của chúng. Điều này có nghĩa là để truy cập một tệp, chúng tôi cần đường dẫn cơ sở (đối với tôi là 'dữ liệu'), thể loại và tên của tệp

Nếu tệp tồn tại, chúng tôi muốn đọc nó, chia nó theo các ký tự dòng mới (‘\n’), lọc các chuỗi trống và trả về các phần văn bản còn lại dưới dạng danh sách. Trong trường hợp, tệp không tồn tại (e. g. số tệp lớn hơn số tệp có sẵn), chúng tôi muốn trả về một danh sách trống. Tôi thích điều này hơn là làm việc với các ngoại lệ hoặc không trả lại, nếu tệp không tồn tại

def read_and_split_file(self, genre: str, file_name: str) -> list:
text_data = list()
current_file = os.path.abspath(os.path.join('data', genre, file_name))
if os.path.exists(current_file):
open_file = open(current_file, 'r', encoding="latin-1")
text_data = open_file.read().split('\n')
text_data = list(filter(None, text_data))
return text_data

Như bạn có thể thấy trong đoạn mã trên, sử dụng gói os. Vì vậy, chúng ta cần nhập gói này

Trích xuất thông tin

Để trích xuất thông tin của các tệp văn bản và chuẩn bị cho bước tiếp theo, tôi khuyên bạn nên theo đuổi điều này cho mọi thể loại. Điều này có nghĩa là chúng tôi lặp qua mọi tệp trong thư mục của thể loại tương ứng. Bằng cách giữ một biến current_number, chúng ta có thể định dạng tên tệp bằng các số 0 đứng đầu, sau đó đọc và chia nhỏ tệp bằng cách gọi phương thức đã triển khai ở trên

Nếu danh sách được trả về trống, chúng tôi muốn dừng vòng lặp, vì điều này có nghĩa là chúng tôi đã đi đến cuối vòng lặp và không còn tệp mới nào trong thư mục

Mặt khác, chúng tôi thêm thông tin trả về của chức năng đọc và tách vào các vùng chứa dữ liệu cụ thể, chẳng hạn như tiêu đề, phụ đề và văn bản. Vì tôi đã đề xuất cung cấp số lượng mã thông báo của văn bản trong đầu ra cuối cùng, nên chúng tôi có thể sử dụng gói nltk để mã hóa văn bản và thêm độ dài của danh sách mã thông báo vào danh sách token_counts của chúng tôi. Cuối cùng, chúng tôi tăng số_hiện tại lên 1 để tiếp tục quá trình giải nén với tệp tiếp theo

def extract_genre_files(self, genre: str) -> pd.DataFrame:
found = True
current_number = 1
titles = list()
subtitles = list()
texts = list()
token_counts = list()
while found:
file_name = "{:03d}.txt".format(current_number)
text_data = self.read_and_split_file(genre, file_name)
if len(text_data) != 0:
titles.append(text_data[0])
subtitles.append(text_data[1])
article_text = ' '.join(text_data[2:])
texts.append(article_text)
token_counts.append(len(nltk.word_tokenize(article_text)))
current_number += 1
else:
found = False

genres = [genre] * len(titles)
data = {'genre': genres, 'title': titles, 'subtitle': subtitles, 'text': texts, 'token_counts': token_counts}
data_frame = pd.DataFrame(data)
return data_frame

Sau khi kết thúc vòng lặp qua các tệp thể loại, chúng tôi tạo khung dữ liệu dựa trên thông tin trích xuất được lưu trữ bên trong danh sách cụ thể. Tương tự như bước trước, chúng ta cần nhập hai gói (nltk và pandas). Ngoài ra, vui lòng đảm bảo rằng bạn đã tải xuống dữ liệu 'punkt' của gói nltk, vì cần phải mã hóa văn bản

import nltk
# nltk.download('punkt')
import pandas as pd

Xây dựng khung dữ liệu

Ở bước cuối cùng, chúng ta phải tạo một vòng lặp qua các thể loại hiện có, trích xuất thông tin cho mỗi thể loại bằng cách gọi phương thức đã triển khai ở trên, nối đầu ra cho mọi thể loại và cuối cùng lưu khung dữ liệu được nối dưới dạng csv với dấu tách mong muốn

def transform_texts_to_df(self, name, genre_list, delimiter = '\t'):
article_df_list = list()
for genre in genre_list:
article_df_list.append(self.extract_genre_files(genre))
df = pd.concat(article_df_list)
df.to_csv(name, sep=delimiter)
return df

Sau khi triển khai lớp và phương thức của nó, chúng ta cần tạo một thể hiện của lớp ArticleCSVParser và gọi phương thức transform_texts_to_df bằng cách cung cấp tên mong muốn cho csv kết quả và một danh sách chứa mọi thể loại. Et voilà

if __name__ == "__main__":
genre_list = ['business', 'entertainment', 'politics', 'sport', 'tech']
parser = ArticleCSVParser()
df = parser.transform_texts_to_df('bbc_articles.csv', genre_list)
print(df.head())
. Kết luận

Trong bài viết này, tôi đã hướng dẫn cách chuyển đổi tệp văn bản thành khung dữ liệu và lưu dưới dạng tệp csv/tsv. Để sử dụng lại lớp cho một tập dữ liệu khác, chỉ cần tạo một lớp mới kế thừa từ Article CSVParser và ghi đè các phương thức phải thay đổi