خیلی ساده regex یا عبارات منظم در پایتون یاد بگیر

عبارات منظم در پایتون

فهرست مطالب

استخراج اطلاعات (Information Extraction) با استفاده  Regular Expression

تا اینجای کار به کمک مفاهیم آموزش‌داده‌شده و استفاده از کتابخانه‌ nltk و کتابخانه spacy در پایتون، می‌توانیم داده متنی تمیزی داشته باشیم. در ادامه لازم است کار با عبارات منظم در پایتون را یاد بگیریم، چون در دنیای واقعی به طور مثال متن‌ شبکه‌های اجتماعی و آنلاین، باید با نویزهای زیادی دست‌وپنجه نرم کنیم. مانند تگ‌های HTML هنگام scrape کردن یک صفحه، ایموجی‌های به‌کاررفته در توییت‌ها، لهجه‌های مختلف زبان فرانسوی، آدرس‌های اینترنتی (URLs) و ایمیل‌ها.

نیاز داریم که این چالش‌ها را به نوعی حل کرده و از شر آن‌ها خلاص شویم!

آموزش عبارات منظم در پایتون

بیایید با چالشی ساده و در عین‌حال مفید شروع کنیم، یعنی تمام هشتگ‌های یک پست از یک شبکه اجتماعی را بیرون بکشیم.

استخراج Hashtags

فرض کنید یک مجموعه توییت داریم و می‌خواهیم تمام هشتگ‌های درج شده در آن‌ها را استخراج کنیم. به طور دقیق‌تر، می‌خواهیم تمام رشته‌هایی که با علامت #  شروع می‌شوند را بیرون بکشیم.

برای این کار می‌توانیم از یک کتابخانه عبارات منظم در پایتون به نام regex استفاده کنیم که به ما این امکان را می‌دهد تا:

  • یک الگوی رشته‌ای (string pattern) تعریف کنیم. این الگو می‌تواند کم‌وبیش ساده یا پیچیده باشد اما باید دقیق باشد.
  • روی رشته‌هایی که با الگوی تعریف شده مطابقت دارند، عملیات مختلفی مانند جستجو (search)، استخراج (extract) و جایگزینی (replace) انجام دهیم.

کدی که همه hashtagهای یک متن را پیدا می‌کند، به این صورت است:

				
					# the source text
text = ' _ _ _ _ _ ... '

# 1. import the regex library
import re

# 2. define the pattern
pattern = r'#\S+'

# 3. find all the strings that match the pattern with the findall method
re.findall(pattern, text)

				
			

اگر الگوی

				
					r'#\S+'
				
			

برایتان عجیب و ناآشنا به نظر می‌رسد، نگران نباشید، در ادامه مقاله عبارات منظم در پایتون به تعریف آن می‌پردازیم. در حال حاضر، می‌خواهیم این کد را برای سه جمله از سه توییت اجرا کنیم:

				
					. An #autumn scene showing a beautiful #horse coming to visit me.
. My new favorite eatery in #liverpool! and I mean superb! #TheBrunchClub #breakfast #food.
. #nowplaying Pointer Sisters - Dare Me | #80s #disco #funk #radio.
				
			
				
					# the corpus of tweets
tweets = [
    'An #autumn scene showing a beautiful #horse coming to visit me.', 
    'My new favourite eatery in #liverpool and I mean superb! #TheBrunchClub #breakfast #food', 
    '#nowplaying Pointer Sisters - Dare Me | #80s #disco #funk #radio']
    
# and the hashtag extraction
import re
pattern = r'#\S+'
for text in tweets:
    print(re.findall(pattern, text))

				
			

خروجی کد به این شکل خواهد بود:

				
					['#autumn', '#horse']
['#liverpool', '#TheBrunchClub', '#breakfast', '#food']
['#nowplaying', '#80s', '#disco', '#funk', '#radio']

				
			

بسیار عالی! به‌این‌ترتیب، همه hashtagهایی که در سه جمله به‌کاررفته بودند را بیرون کشیدیم!

یکی دیگر از استراتژی‌های استخراج hashtag می‌تواند این باشد که متن را tokenize کرده و فقط token‌هایی را که با # شروع می‌شوند را نگه داریم. بااین‌حال، این روش برای شناسایی string patternهای پیچیده‌تر مانند ایمیل‌ها، URL ها، لیستی از کلمات و ... قابل‌استفاده نیست.

استخراج Usernames@

نام‌های کاربری (Usernames) که با علامت @ شروع می‌شوند را می‌توان با روش مشابهی استخراج کرد. فقط باید در تعریف regex برای پردازش عبارات منظم در پایتون، به‌جای علامت #، از علامت @ استفاده کنیم:

				
					import re
text = 'Check out this new NLP course on @openclassrooms by @alexip'
    
# change the pattern # -> @
pattern = r'@\S+' 
print(re.findall(pattern, text))

				
			

به‌این‌ترتیب، خروجی زیر را خواهیم داشت:

				
					['@openclassrooms', '@alexip']
				
			

تا اینجای کار آموزش regex، الگوهای تعریف شده بسیار ساده بودند زیرا فقط لازم بود اولین کاراکتر یک رشته را تشخیص دهیم.

دوست دارید پروژه‌هایی برای پردازش متن یاد بگیرید که در کارهای دنیای واقعی استفاده می‌شوند؟ صفحه آموزش متن کاوی فارسی با شبکه‌های عصبی را ببینید.

Regex چیست؟

Regex مخفف عبارت regular expression (عبارت‌های منظم) است. در واقع دنباله‌ای از کاراکترها است که یک الگوی جستجو را تعریف می‌کند. این الگو به ما امکان می‌دهد پردازش عبارات منظم در پایتون را با سه عملیات تطابق (match)، استخراج (extract) یا تغییر (modify) روی هر متن دلخواه اجرا کنیم.

 هنگامی که یک الگو را تعریف کنیم، می‌توانیم از آن برای کاربردهای مختلفی در متن استفاده کنیم. کتابخانه پایتونی re شامل سه تابع اصلی زیر می‌شود:

  • findall(pattern, text): لیست رشته‌هایی را که با الگو مطابقت دارند، برمی‌گرداند.
  • sub(pattern, replace_with, text): دنباله‌های رشته‌ای را که با الگوی تعریف شده مطابقت دارند، با دنباله replace_with جایگزین می‌کند.
  • search(pattern, text): آخرین رشته منطبق با الگوی تعریف شده را به همراه شروع و پایان انطباق الگو، برمی‌گرداند.

در پردازش عبارات منظم در پایتون، درحالی‌که findall لیستی از رشته‌های منطبق (matching strings) را برمی‌گرداند، در search و match اگر الگوی تعریف شده پیدا شود، یک match object و اگر پیدا نشود، None برمی‌گردانند. یک match object شامل محل شروع و پایان الگو در رشته است. برای اطلاعات بیشتر به regex documentation مراجعه کنید.

در ادامه آموزش regex از تابع re.sub برای حذف همه تگ‎های HTML از یک صفحه HTML استفاده می‌کنیم.

حذف تگ‌های HTML

فرض کنید که یک صفحه وب را دانلود کرده‌ایم و با پردازش عبارات منظم در پایتون، می‎خواهیم متن آن را بدون هیچ نشانه‌گذاری (HTML markup)، استخراج کنیم. برای این کار می‌توانیم از regex استفاده کنیم؛ یعنی می‌توانیم الگویی تعریف کنیم که همه رشته‌های موجود بین دو علامت > و < را پیدا کند:

				
					import requests
import re

# Music is in the House!
url = 'https://en.wikipedia.org/wiki/House_music'

# GET the content 
# Note: requests.get().content returns a byte object 
# that we can cast as string with .decode('UTF-8')
html = requests.get(url).content.decode('UTF-8')

# remove the header part of the html 
html = html.split('</head>')[1]

# and remove all the html tags
text = re.sub("<[^>]*>",' ', html)

				
			

به طور مثال، اگر کاراکتر 540 تا 799 آن را print بگیریم: print(text[540:800])

خروجی زیر را خواهیم داشت:

				
					Cultural origins  1980s,  Chicago ,  Illinois , United States    Derivative forms      Electroclash    Eurobeat    techno    UK garage    speed garage    trance    dance-pop    2-step garage    Detroit techno        Subgenres        Acid house    deep
				
			

استخراج URLs

در ادامه بررسی عبارات منظم با پایتون می‌خواهیم یک مقاله ویکی‌پدیا را انتخاب کرده و URLهای موجود در متن صفحه HTML خام آن را استخراج کنیم.

همه URLها با نام پروتکل شروع می‌شوند (مانند HTTP، FTP و …). در این بخش از مقاله، ما با پروتکل HTTP که استانداردی برای URL وب‌سایت‌ها هست، کار می‌کنیم.

به نظر شما، آیا می‌توانیم برای کار با عبارات منظم در پایتون، همانند مثال‌های قبل، علامت # که در hashtag# استفاده می‌شود را تغییر دهیم و URLها را شناسایی کنیم؟

متأسفانه الگوی URLها، تا این حد ساده نیست. برای hashtags# و usernames@ پیچیدگی خاصی نداشتیم زیرا با علامت‌های # و @ شروع شده و تا جایی ادامه دارند که از space، tab و line return استفاده شده باشد.

اما در یک صفحه HTML خام، می‌توانیم URLهایی داشته باشیم که انتهای آن‌ها علامت double quote (“) یا علامت پایان تگ (<) داشته باشند؛ بنابراین باید الگوهایی را مشخص کنیم تا علاوه بر اینکه با http شروع می‌شوند، (“,> ,;) را به عنوان کاراکترهای انتهایی داشته باشند.

الگوی پیداکردن URLها کمی پیچیده‌تر است:

				
					r'http.+?(?="|<)'
				
			

می‌توانیم آن را بر روی یک نمونه از محتوای HTML تست کنیم:

				
					import requests, re
url = 'https://en.wikipedia.org/wiki/House_music'
# GET, decode and drop header
html = requests.get(url).content.decode('UTF-8').split('</head>')[1]
# find all the urls
pattern = r'http.+?(?="|<)'
urls = re.findall(pattern, html)

				
			

در این حالت، urls شامل لیست ۳۳۰تایی از URLهایی است که در صفحه ویکی‌پدیا House Music پیدا می‌شوند. به طور مثال، urls[80] آدرس زیر را دارد:

				
					'https://www.electronicbeats.net/juan-atkins-about-kraftwerk/'
				
			

مشابه با الگوهایی که تا کنون بررسی کردیم، می‌توانیم انواع المان‌ها یعنی (ایمیل‌ها، punctuations، اعداد، کد پستی، شماره‌تلفن و …) را با الگوهای مختلف پیدا کرده و یا جایگزین کنیم.

اگر می‌خواهید کار بر روی پروژه‌های واقعی NLP را یاد بگیرید، دوره آموزش پردازش زبان طبیعی مقدماتی را از دست ندهید.

خلاصه‌ای از Main Regex Patterns

در این قسمت، جدولی از الگوهای مفید و پرکاربرد regex آورده شده است:

regex tutorial

ساختن Regex Patterns

احتمالا متوجه شدید که ما تاکنون در مورد نحوه ساختن regex در پردازش عبارات منظم در پایتون توضیحی ندادیم، این کار چند دلیل دارد:

اولاً ممکن است که در ابتدا، regex سخت و پیچیده به نظر برسد و خواستیم با دیدن چند مثال این تصور را از بین ببریم.

ثانیاً، ساختن یک regex pattern درست و مناسب برای عبارات منظم در پایتون، می‌تواند زمان‌بر و همراه با آزمون‌ و خطا باشد. هنگام پیاده‌سازی پروژه‌ها، می‌توانیم به‌راحتی هرآنچه را که دنبالش هستیم، در گوگل جستجو کرده و از فرشته نجات خود یعنی Stack Overflow کمک بگیریم و regex pattern موردنظر خود را پیدا کنیم.

توصیه می‌شود که regex به‌دست‌آمده را بر روی چند مثال تست کنید تا از آن مطمئن شوید. (تاحدامکان، خودتان regex pattern نسازید. البته که ممکن است بسته به نیاز پروژه لازم باشد که این کار را بکنید اما برای regex patternهای پرکاربرد و معروف مانند ایمیل، شماره‌تلفن و … کافی است فقط آن را جستجو کنید.)

البته ما برای درک بهتر regex، نحوه ساختن آن را توضیح می‌دهیم!

Regex دنباله ای از کاراکترها است که این کاراکترها بر اساس مؤلفه یا اجزای تشکیل‌دهنده رشته (Components)، میزان تکرار (Repetition) و چگونگی جداسازی (Boundries) آن‌ها مشخص می‌شوند.

مؤلفه‌ها یا اجزا (Components):

هریک از علائم زیر، بیانگر اطلاعات خاصی هستند:

  • []: مجموعه‌ای از کاراکترها
  • a-z: حروف کوچک انگلیسی
  • A-Z: حروف بزرگ انگلیسی
  • À-ÖØ-öø-ÿ : حروف تلفظی (accented letters)
  • \d: اعداد، معادل با [0-9]
  • \S: هر کاراکتری به جز کاراکتر space
  • \w: کاراکترهای کلمه‌ای که شامل اعداد و زیرخط (underscore) می‌شود.
  • \s: انواع مختلفی از کاراکتر space، مانند line returns، tabs و non-breaking space

تکرار (Repetition):

  • + : 1 تکرار و یا بیشتر
  • ? : 0 یا 1 تکرار
  • * : 0 یا بیشتر

مرزها (Boundaries):

  • \b: رشته خالی که فقط باید در ابتدا یا انتهای کلمه بیاید؛ بنابراین یک word tokenizer می‌تواند الگویی مانند r’\b\w\b’ داشته باشد.
  • ^ : از ابتدای متن (یعنی از ابتدای متن، باید الگوی موردنظر را داشته باشیم)
  • $ : تا انتهای متن (یعنی تا انتهای متن، باید الگوی موردنظر را داشته باشیم)

سایت‌هایی برای عبارات منظم در پایتون وجود دارند و می‌توان از آن‌ها برای ساختن و تست کردن regex patterns استفاده کرد. Regex 101 نمونه خوبی از آن‌ها است که می‌توانید در آدرس https://regex101.com آن را تست کنید.

ممکن است این سوال برایتان پیش بیاید که چرا برای تعریف regex patterns، باید آن را با r شروع کنیم؟ با نوشتن r قبل از رشته (string) مورد نظر، در واقع یک رشته خام (raw string) ایجاد می‌کنیم. دقت کنید که اولین حرف از کلمه raw، حرف r است. بنابراین r string را به‌صورت  ’ ‘r خواهیم داشت. در یک raw string، کاراکترهای کنترلی (escaped characters) مانند n\ که line return است، معنی ندارد. به همین دلیل است که ترجیح می‌دهیم در regex patterns از raw string استفاده کنیم. برای درک بهتر تفاوت بین string و raw string می‌توانید نتایج print(‘\n’) و print(r’\n’) را با هم مقایسه کنید که اولی فقط return line باز می‌گرداند ولی در دومی n\ چاپ می‌شود.

پیش‌پردازش یک Regex Pattern

تاکنون مثال‌هایی از regex را دیده‌اید که به‌صورت یک‌رشته تعریف شده و در توابع sub و findall استفاده شده‌اند.

علاوه بر این موارد، با دستور re.compile(string) می‌توانیم regex patterns تعریف شده برای عبارات منظم در پایتون را precompile کنیم:

				
					import re
pattern = re.compile(r'@\S+')
re.findall(pattern, text)

				
			

precompile کردن regex، سرعت اجرای برنامه را برای کار با عبارات منظم در پایتون به طور چشم‌گیری افزایش می‌دهد. می‌توانیم زمانی که با حجم زیادی از داده‌ها سروکار داریم، از آن استفاده کنیم.

شاید در مورد Beautiful Soup شنیده باشید. کتابخانه Beautiful Soup، ابزار مناسبی برای information extraction از یک صفحه HTML است. می‌توانیم اطلاعات مربوط به تگ‌های HTML را به کمک آن استخراج کنیم. به این صورت که از href برای استخراج URLها و از اسم div برای به‌دست‌آوردن محتوای متنی، استفاده کنیم. اما اگر بخواهیم که فقط با استفاده از داده متنی information extraction کنیم، regex سریع‌تر است.

اگر به بحث‌های مرتبط با جمع‌آوری داده، وب اسکرپینگ و آشنایی بیشتر با کتابخانه Beautiful Soup علاقه‌مند هستید آموزش رایگان وب اسکرپینگ را در کانال یوتیوب دیتاهاب از دست ندهید.

regex تنها برای پردازش عبارات منظم در پایتون نیست و ابزار قدرتمندی است که می‌توان در زبان‌های مختلفی مانند C، PHP، Java، Go، Julia ، Haskell، R و حتی در command line از آن استفاده کرد. اگرچه بین ورژن‌های مختلف regex، تغییرات جزئی وجود دارد، اما در همه آن‌ها تعریف الگوها یکسان است. به طور پیش‌فرض در command line و اکثر دستورات آن می‌توانیم از regex استفاده کنیم. فرض کنید که در یک directory، تعداد زیادی فایل text داریم و می‌خواهیم که ایمیل‌های موجود در همه این فایل‌ها را استخراج کنیم. برای این کار می‌توانیم که الگوی ایمیل را grep کنیم تا لیستی از ایمیل‌ها را دریافت کنیم.
				
					> grep 'r'\S*@\S*\s?' files.txt 
				
			

دقت کنید که grep یک UNIX command است و در سیستم عاملی مانند Windows قابل‌استفاده نیست.

  • Regex مخفف عبارت regular expression (عبارت‌های منظم) است. در واقع دنباله ای از کاراکترها است که یک الگوی جستجو را تعریف می‌کند. این الگو به ما امکان می‌دهد سه عملیات تطابق (match)، استخراج (extract) و تغییر (modify) را روی هر متن دلخواه اجرا کنیم.
  • می‌توانیم از regex از پیش تعریف شده (pre-defined regex) برای استخراج المان‌های متنی ساده و پرکاربرد مانند usernames یا hashtags استفاده کنیم. در این قسمت از آموزش regex، با برخی از پرکاربردترین الگوها و نحوه استفاده از آن‌ها برای استخراج اطلاعات از متن آشنا شدیم.
  • همچنین می‌توانیم از regex برای پاک‌سازی (clean up) متن استفاده کنیم؛ یعنی تگ‌های ناخواسته و المان‌های پیچیده‌تری که معنا و مفهوم مفیدی ندارند را حذف کنیم.
  • Regex بسیار سریع است و می‌توان از آن در command line و اکثر زبان‌های برنامه‌نویسی استفاده کرد.

در این مقاله، بخش اول مقالات آموزشی پردازش زبان طبیعی در پایتون، یعنی پیش‌پردازش داده‌های متنی به پایان رسید. بخش بعدی را با مقاله bags of words چیست شروع می‌کنیم و در مورد نحوه استخراج بردار کلمات یک متن (transform text into numbers)، برای استفاده در پروژه‌های یادگیری ماشین صحبت خواهیم کرد!

هنوز منبع خوبی برای آموزش یادگیری ماشین پیدا نکردید؟ دوره آموزش یادگیری ماشین به زبان ساده با پایتون را رایگان در کانال یوتیوب دیتاهاب ببینید.

مطالب بیشتر

دیدگاهتان را بنویسید