정규표현식을 활용해 문자열 데이터를 다루는 다양한 방법을 소개합니다.

정규표현식 (regular expression)

  • 특정한 패턴과 일치하는 문자열를 ‘검색’, ‘치환’, ‘제거’ 하는 기능을 지원한다.

  • 정규표현식의 도움없이 패턴을 찾는 작업(Rule 기반)은 불완전 하거나, 작업의 cost가 높다.


  • e.g) 이메일 형식 판별, 전화번호 형식 판별, 숫자로만 이루어진 문자열 등

raw string

  • 문자열 앞에 r이 붙으면 해당 문자열이 구성된 그대로 문자열로 변환
1
2
3
4
5
a = 'abcdef\n' # \n : escapce 문자열 (enter의미)
print(a)

b = r'abcdef\n' # escape 문자열이 적용되지 않는다.
print(b)
abcdef

abcdef\n
  • 정규표현식에서 패턴은 raw string으로 이뤄진다.

  • 특정 표현식은 ‘' 와 함께 이뤄지는 경우가 대부분이다.

기본 패턴

  • a, X, 9 등등 문자 하나하나의 character들은 정확히 해당 문자와 일치

    • e.g) 패턴 test는 test 문자열과 일치

    • 대소문자의 경우 기본적으로 구별하나, 구별하지 않도록 설정 가능

  • 몇몇 문자들에 대해서는 예외가 존재하는데, 이들은 특별한 의미로 사용 됨

    • . ^ $ * + ? { } [ ] \ ( )
  • . (마침표) - 어떤 한개의 character와 일치 (newline(엔터) 제외)

  • \w - 문자 character와 일치 [a-zA-Z0-9_]

  • \s - 공백문자와 일치

  • \t, \n, \r - tab, newline, return

  • \d - 숫자 character와 일치 [0-9]

  • ^ = 시작, $ = 끝 각각 문자열의 시작과 끝을 의미

  • \가 붙으면 스페셜한 의미가 없어짐. 예를들어 \.는 .자체를 의미 \\는 \를 의미

  • 자세한 내용은 링크 참조 https://docs.python.org/3/library/re.html

search method

  • 첫번째로 패턴을 찾으면 match 되는 객체를 반환

  • 패턴을 찾지 못하면 None 반환

  • ‘search(정규표현식 패턴, 찾을 대상이 되는 문자열)’ 와 같은 형태로 사용한다.

  • 일치하는 패턴이 있는 경우 = 매치되는 객체를 반환한다.

1
2
3
4
5
6
7
import re # 정규표현식 모듈 불러오기

m = re.search(r'abc', '123abcdef') #123abdef 에서 'abc'라는 패턴을 찾아라(abc가 해당 문자열에 있는지 없는지)

print(type(m))

print(m)
<class 're.Match'>
<re.Match object; span=(3, 6), match='abc'>
  • 일치 하는 패턴이 없는 경우 = None 출력한다.
1
2
3
4
5
m = re.search(r'abc', '123abdef') #123abdef 에서 'abc'라는 패턴을 찾아라(abc가 해당 문자열에 있는지 없는지)

print(type(m))

print(m)
<class 'NoneType'>
None
1
2
3
4
5
6
7
m = re.search(r'abc' , 'abcdef')

print(m.start()) # 해당 문자열에서 패턴이 검색된 위치의 시작 index
 
print(m.end())  # 해당 문자열에서 패턴이 검색된 위치의 끝 index

print(m.group()) # 해당 검색된 패턴 자체를 출력
0
3
abc
  • m.start() 와 m.end()은 각각 패턴이 검색된 문자열의 시작점과 끝점의 index를 의미

  • 이때 표현되는 start와 end의 값은 시작점은 포함, 끝지점은 포함하지 않는다.

  • abcdef에서 abc가 검색된 지점은 [abc]def이다.즉, 시작점은 0번째 string인 a이고, 끝지점은 2번째 index인 c에서 끝나서 end의 출력물은 3이 된다.

1
2
3
4
5
6
7
m = re.search(r'abc' , '123abcdef')

print(m.start()) # 해당 문자열에서 패턴이 검색된 위치의 시작 index
 
print(m.end())  # 해당 문자열에서 패턴이 검색된 위치의 끝 index

print(m.group()) # 해당 검색된 패턴 자체를 출력
3
6
abc

abc가 검색되는 위치가 변경되었다.

  • \d - 숫자 character와 일치 [0-9]
1
2
3
4
m = re.search(r'\d\d', '112abcdef119') # \d\d : 숫자 2개가 연달아 나오는 패턴이 있는가? 
m

# search 함수는 여러개의 패턴이 검색되면 '가장 먼저' 확인되는 패턴을 return한다.
<re.Match object; span=(0, 2), match='11'>
1
2
m = re.search(r'\d\d\d\d', '112abcdef119') # \d\d\d\d : 숫자 4개가 연달아 나오는 패턴이 있는가?
m # None 이므로 print() 없이는 아무것도 출력되지 않는다.
  • \w - 문자 character와 일치 [a-zA-Z0-9_]
1
2
m = re.search(r'\d\d\d\w', '112abcdef119') # \d\d\d\w : 숫자 3개와 문자1개 패턴으로 나오는 패턴이 있는가?
m
<re.Match object; span=(0, 4), match='112a'>
  • . (마침표) - 어떤 한개의 character와 일치 (newline(엔터) 제외)
1
2
m = re.search(r'..\w\w', '@#$%ABCDabcd') # ..\w\w : 어떤 문자든지 2개가 나오고 문자 character 2개가 연달아 나오는 패턴이 있는가?
m
<re.Match object; span=(2, 6), match='$%AB'>

metacharacters (메타 캐릭터) :

’[]’ 문자들의 범위를 나타내기 위해 사용

  • [] 내부의 meta character는 순수하게 문자열을 의미(위의 기본 패턴 처럼 어떤 특정 의미를 갖지 않는다)

e.g)

  • [abck] : a or b or c or k

  • [abc.^] : a or b or c or . or ^

  • [a-d] : -와 함께 사용되면 해당 문자 사이의 범위에 속하는 문자 중 하나 (즉, a부터 d사이중 하나)

  • [0-9] : 모든 숫자

  • [a-z] : 모든 소문자

  • [A-Z] : 모든 대문자

  • [a-zA-Z0-9] : 모든 알파벳 문자 및 숫자

  • [^0-9] : ^가 맨 앞에 사용 되는 경우 해당 문자 패턴이 아닌 것과 매칭. ,즉 ’^’는 not을 의미

  • [abck] : a or b or c or k

1
re.search(r'[cbm]at', 'cat') # [cbm] 중 한개 + at 라는 패턴이 있는가?
<re.Match object; span=(0, 3), match='cat'>
1
2
3
re.search(r'[cbm]at', 'aat') # [cbm] 중 한개 + at 라는 패턴이 있는가?

# 일치하는 값이 없음 = None = 아무것도 출력되지 않음 
  • [0-9] : 모든 숫자
1
2
3
re.search(r'[0-4]pattern', '7pattern') # [0-4]의 숫자중 1개 + pattern 라는 패턴이 있는가?

# 7은 0~ 4 사이의 숫자가 아니므로 None
1
re.search(r'[0-9]pattern', '7pattern') # [0-9]의 숫자중(모든수) 1개 + pattern 라는 패턴이 있는가?
<re.Match object; span=(0, 8), match='7pattern'>
  • [^0-9] : ^가 맨 앞에 사용 되는 경우 해당 문자 패턴이 아닌 것과 매칭. ,즉 ’^’는 not을 의미
1
re.search(r'[^abc]aron', '0aron') # ^abc : ^ or a or b or c + aron 이란 패턴이 있는가?
<re.Match object; span=(0, 5), match='0aron'>
1
re.search(r'[abc.^]aron', 'caron') # abc.^ : a or b or c or . or ^ + aron 이란 패턴이 있는가?
<re.Match object; span=(0, 5), match='caron'>
1
re.search(r'[abc.^]aron', 'daron') # abc.^ : a or b or c or . or ^ + aron 이란 패턴이 있는가?
  • [^0-9] : ^가 맨 앞에 사용 되는 경우 해당 문자 패턴이 아닌 것과 매칭. ,즉 ’^’는 not을 의미
1
re.search(r'[^abc.]aron', 'daron') # ^abc. : a or b or c or . 가 아닌 것 + aron 이란 패턴이 있는가?
<re.Match object; span=(0, 5), match='daron'>

반복패턴

  • 패턴 뒤에 위치하는 *, +, ?는 해당 패턴이 반복적으로 존재하는지 검사

    • ’+’ -> 1번 이상의 패턴이 발생

    • ‘*’ -> 0번 이상의 패턴이 발생

    • ’?’ -> 0 혹은 1번의 패턴이 발생

  • 반복을 패턴의 경우 greedy하게 검색 함, 즉, 가능한 많은 부분이 매칭되도록 한다.

  • e.g) a[bcd]*b 패턴을 abcbdccb에서 검색하는 경우

    • ab, abcb, abcbdccb 전부 가능 하지만 최대한 많은 부분이 매칭된 abcbdccb가 검색된 패턴
  • ‘*’ -> 0번 이상의 패턴이 발생

1
re.search(r'a[bcd]*b', 'abcbdccb') # [bcd] 중 하나가 0번이상 반복되고(0번포함) + b인 패턴
<re.Match object; span=(0, 8), match='abcbdccb'>
  • ’+’ -> 1번 이상의 패턴이 발생
1
re.search(r'b\w+a', 'banana') # b\w+a : b로 시작해서 어떤 숫자나 영문자(\w)가 1번이상 발생(+)하고 그 뒤에 a가 붙은 패턴이 있는가?
<re.Match object; span=(0, 6), match='banana'>
1
2
3
re.search(r'i+', 'piigiii') # i+ : i가 1번 이상 포함된 패턴이 있는가?

# search함수는 가장 먼저 찾아지는 첫번째 것을 검색하는 순간 멈춘다. 
<re.Match object; span=(1, 3), match='ii'>

’+’‘*‘의 차이

1
re.search(r'pi+g', 'piig')
<re.Match object; span=(0, 4), match='piig'>
1
re.search(r'pi*g', 'piig')
<re.Match object; span=(0, 4), match='piig'>
1
re.search(r'pi+g', 'pig') # pi+g : 
<re.Match object; span=(0, 3), match='pig'>
1
re.search(r'pi*g', 'pig')
<re.Match object; span=(0, 3), match='pig'>

’+’는 최소 1번, ‘*’ 는 최소 0번이기 때문에 위의 경우 차이가 없지만, 아래 처럼 ‘i’가 아예 없는 경우라면 그 차이가 보인다.

1
re.search(r'pi+g', 'pg') # pi+g : 
1
re.search(r'pi*g', 'pg')
<re.Match object; span=(0, 2), match='pg'>
  • ’?’ -> 0 혹은 1번의 패턴이 발생
1
re.search(r'https?', 'http://www.naver.com')
<re.Match object; span=(0, 4), match='http'>
1
re.search(r'https?', 'httpt://www.naver.com')
<re.Match object; span=(0, 4), match='http'>
1
re.search(r'https?', 'httpq://www.naver.com')
<re.Match object; span=(0, 4), match='http'>

사실상 https? 에서 s는 없어도 상관없다.

기본 패턴 **


  1. 다른 문자와 함께 사용되어 특수한 의미를 갖게 된다.
  • 대문자는 소문자 패턴 조건의 not을 의미한다.

e.g)

  • \d : 숫자를 [0-9]와 동일

  • \D : 숫자가 아닌 문자 [^0-9]와 동일

  • \s : 공백 문자(띄어쓰기, 탭, 엔터 등)

  • \S : 공백이 아닌 문자

  • \w : 알파벳대소문자, 숫자 [0-9a-zA-Z]와 동일

  • \W : non alpha-numeric 문자 [^0-9a-zA-Z]와 동일

  1. 메타 캐릭터가 캐릭터 자체를 표현하도록 할 경우 사용
  • \. , \\

  • \s : 공백 문자(띄어쓰기, 탭, 엔터 등)

1
re.search('\sand', 'apple and banana') # \sand :  공백 문자 + and 인 패턴이 있는가?
<re.Match object; span=(5, 9), match=' and'>
  • \S : 공백이 아닌 문자
1
re.search(r'\Sand', 'apple land banana') # \Sand : 공백 없음+and 라는 패턴이 있는가?
<re.Match object; span=(6, 10), match='land'>

메타 캐릭터가 캐릭터 자체를 표현하도록 할 경우

  • \. , \\

  • 원래 메타 표현식에서 .는 ‘모든 문자’를 의미

’.’이 들어간 패턴을 찾고 싶을때

잘못된 검색법

1
re.search(r'.and', '.and')
<re.Match object; span=(0, 4), match='.and'>
1
re.search(r'.and', 'Aand')
<re.Match object; span=(0, 4), match='Aand'>

정확한 예시 : \를 사용해줘야 한다.

1
re.search(r'\.and', '.and')
<re.Match object; span=(0, 4), match='.and'>
1
re.search(r'\.and', 'Aand')

기본 패턴 .

  • 모든 문자를 의미
1
re.search(r'p.g', 'pig')
<re.Match object; span=(0, 3), match='pig'>

기본 패턴 ^, $

  • ^ 문자열의 맨 앞부터 일치하는 경우 검색

  • $ 문자열의 맨 뒤부터 일치하는 경우 검색

  • ^ 문자열의 맨 앞부터 일치하는 경우 검색

1
re.search(r'b\w+a', 'cabana') # b\w+a :  b로 시작해서 어떤문자(\w)하나이상이 나오고 a가 나오는 패턴이 있는가?
<re.Match object; span=(2, 6), match='bana'>
1
2
3
re.search(r'^b\w+a', 'cabana') # ^b\w+a : 문자열의 시작부터 b로 시작해서 어떤문자(\w)하나 이상이 나오고 a가 나오는 패턴이 있는가?

# None이 뜬다. 왜? 검색할 문자열이 'c'로 시작하기 때문 
1
re.search(r'^b\w+a', 'babana') # 문자열의 시작이 b여서 패턴 검색이 된다.
<re.Match object; span=(0, 6), match='babana'>
  • $ 문자열의 맨 뒤부터 일치하는 경우 검색
1
re.search(r'b\w+a$', 'cabana') # b\w+a$ : b로 시작해서 어떤문자(\w)하나 이상이 나오고 끝이 a가 나오는 패턴이 있는가?
<re.Match object; span=(2, 6), match='bana'>
1
2
3
re.search(r'b\w+a$', 'cabanap') # b\w+a$ : b로 시작해서 어떤문자(\w)하나 이상이 나오고 끝이 a가 나오는 패턴이 있는가?

# 맨 끝이 a로 끝나야 되는데 p로 끝나서 None이 된다.

grouping

  • ()을 사용하여 그루핑

  • 매칭 결과를 각 그룹별로 분리 가능

  • 패턴 명시 할 때, 각 그룹을 괄호() 안에 넣어 분리하여 사용

  • 이메일 패턴이 가장 대표적인 예시

1
2
3
4
m = re.search(r'\w+@.+', 'gabe@gmail.com') 
# \w+@.+ : 어떤 문자열이든 1개 이상(\w+)이 나오고 @가 붙고 그 다음에 어떤 문자든 한번(.+) 나오는 패턴?

m.group() #일치하는 패턴 전체를 가져오는 함수
'gabe@gmail.com'

문자열을 찾으면서 ID 와 도메인을 분리해서 가져오고 싶을때?

1
2
3
4
m = re.search(r'(\w+)@(.+)', 'gabe@gmail.com')
print(m.group(1)) # 첫번째 그룹 : (\w+)
print(m.group(2)) # 두번째 그룹 : (.+)
print(m.group(0)) # 모든 그룹
gabe
gmail.com
gabe@gmail.com

처음에 그룹을 사용하는게 어렵다면, 위의 예제 처럼 전체 패턴을 먼저 만들고, ()를 둘러주는 식으로 하면 쉽다.

미니멈 매칭(non-greedy way)

  • 기본적으로 *, +, ?를 사용하면 greedy(맥시멈 매칭)하게 동작한다.

  • *?, +?을 이용하여 해당 기능을 구현

e.g) html 안에 tag가 무엇인지 찾고 싶을 때

1
2
3
즉,  <html>gabe</html><html>을 찾고 싶을때

잘못된 예시

  • 기본적으로 *, +, ?를 사용하면 greedy(맥시멈 매칭)하게 동작한다.
1
re.search(r'<.+>', '<html>gabe</html>')
1
<re.Match object; span=(0, 17), match='<html>gabe</html>'>

greedy 하지 않게 매칭을 하기

  • *?, +?을 이용하여 해당 기능을 구현
1
re.search(r'<.+?>', '<html>gabe</html>')
1
<re.Match object; span=(0, 6), match='<html>'>

기본 패턴

  • *, +, ?을 사용하여 반복적인 패턴을 찾는 것이 가능하나, 반복의 횟수는 제한 불가
  • 패턴뒤에 위치하는 중괄호{}에 숫자를 명시하면 해당 숫자 만큼의 반복인 경우에만 매칭

e.g)

  • {4} - 4번 반복

  • {3,4} - 3 ~ 4번 반복

특정 문자가 정확하게 원하는 숫자만큼 반복되는 패턴을 찾고 싶을때?

1
2
3
re.search('pi+g', 'piiiig')

위 와 같은 예시를 검색할때는 +나 * 등을 써서는 원하는 정확한 문자열을 검색할 수 없다.

piiiig 나 piiig나 piig 등 ~회 이상 이란 조건 때문에 딱 원하는 1개의 패턴만 검색하지 않기 때문 (반복 패턴의 greedy 특성)

  • {nums} - nums번 반복
1
2
3
re.search('pi{3}g', 'piiiiig') # pi{3}g : i가 정확하게 3번만 나오고 g가 나오는 패턴. 즉, piiig를 찾기 위한 입력

# 일치하는 값이 없으므로 None이 된다.
  • {nums1,nums2} - nums1 ~ nums2번 반복
1
re.search('pi{3,5}g', 'piiiiig') # pi{3,5}g : p + i가 3~5회 반복 + g 인 패턴이 있는가?
<re.Match object; span=(0, 7), match='piiiiig'>

기본 패턴 {}? - non-greedy way

  • {m,n}의 경우 m번 에서 n번 반복하나 greedy하게 동작
1
re.search(r'a{3,5}', 'aaaaa')
<re.Match object; span=(0, 5), match='aaaaa'>
  • {m,n}?로 사용하면 non-greedy하게 동작. 즉, 최소 m번만 매칭하면 만족
1
re.search(r'a{3,5}?', 'aaaaa')
<re.Match object; span=(0, 3), match='aaa'>

match method

  • search와 유사하나, 주어진 문자열의 시작부터 비교하여 패턴이 있는지 확인

  • 시작부터 해당 패턴이 존재하지 않다면 None 반환

re.search() 로 한다면 아래의 2개는 모두 동일 결과를 return할 것이다.

1
2
3
4
5
re.match(r'\d\d\d', 'my number is 123')

# None 

# 문자열의 시작부터 패턴이 일치하는지를 확인하는 것이 match 이기 때문
1
re.match(r'\d\d\d', '123 is my number')
<re.Match object; span=(0, 3), match='123'>

즉, search 의 기본 패턴 ^ 와 같다.

1
re.search(r'^\d\d\d', '123 is my number')
<re.Match object; span=(0, 3), match='123'>

findall method

  • search가 최초로 매칭되는 패턴만 반환한다면, findall은 매칭되는 전체의 패턴을 반환

  • 매칭되는 모든 결과를 리스트 형태로 반환

email의 grouping 형식으로 예시

1
2
3
# [\w-]+@[\w.]+ :  [\w-] 패턴이 1개이상(+) + @ + [\w.] 패턴이 1개 이상(+)

re.findall(r'[\w-]+@[\w.]+', 'gabe@gmail.com and gabe2@gmail.com is the list of email')
['gabe@gmail.com', 'gabe2@gmail.com']

sub method

  • 주어진 문자열에서 일치하는 모든 패턴을 replace 한 뒤, 그 결과를 문자열로 다시 반환한다.

  • 두번째 인자는 특정 문자열이 될 수도 있고, 함수가 될 수 도 있다.

  • count가 0인 경우는 전체를, 1이상이면 해당 숫자만큼 치환 된다. (default=1)

1
2
3
re.sub(r'검색할 패턴', 'replace할 문자', '검색 대상' , count= 1 or 0 )

Where count = 0

  • 일치되는 패턴은 모두 바뀐다.
1
re.sub(r'[\w-]+@[\w.]+', 'replaced', 'gabe@gmail.com and gabe2@gmail.com is the list of email', count=0)
'replaced and replaced is the list of email'
1
re.sub(r'[\w-]+@[\w.]+', 'replaced', 'gabe@gmail.com and gabe2@gmail.com is the list of email') # count=0 일 경우 생략 가능
'replaced and replaced is the list of email'

Where count = 1

  • 가장 먼저 일치하는 패턴만 바뀐다.
1
re.sub(r'[\w-]+@[\w.]+', 'replaced', 'gabe@gmail.com and gabe2@gmail.com is the list of email', count=1)
'replaced and gabe2@gmail.com is the list of email'

compile method

  • 동일한 정규표현식을 매번 다시 쓰기 번거로움을 해결

  • compile로 해당표현식을 re.RegexObject 객체로 저장하여 사용가능

1
2
3
4
5
# compile 지정
email_reg = re.compile(r'[\w-]+@[\w.]+')

# 지정된 compile로 search 
email_reg.search('gabe@gmail.com and gabe2@gmail.com is the list of email')
<re.Match object; span=(0, 14), match='gabe@gmail.com'>

간혹 웹스크롤링을 하다보면 “gabe@email.com.” 과 같이 되어있는 경우도 있는데, 이때도 위의 complie한 기준이면 검색해서 결과값을 가져온다.

1
email_reg.search('gabe@gmail.com. and gabe2@gmail.com is the list of email')
<re.Match object; span=(0, 15), match='gabe@gmail.com.'>

이를 방지하기 위해서는 아래와 같이 \w+을 한번더 명시해주는 것이 확실하다.

1
email_reg = re.compile(r'[\w-]+@[\w.]+\w+')
1
email_reg.search('gabe@gmail.com. and gabe2@gmail.com is the list of email')
<re.Match object; span=(0, 14), match='gabe@gmail.com'>
1
2
# 지정된 compile로 findall 
email_reg.findall('gabe@gmail.com and gabe2@gmail.com is the list of email')
['gabe@gmail.com', 'gabe2@gmail.com']

실제 정규표현식 활용 예시

웹 스크롤링한 뉴스에서 이메일 주소를 추출하기

뉴스 스크롤링

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
import requests
from bs4 import BeautifulSoup
# 위의 두 모듈이 없는 경우에는 pip install requests bs4 실행

def get_news_content(url):
    response = requests.get(url)
    content = response.text

    soup = BeautifulSoup(content, 'html5lib')

    div = soup.find('div', attrs = {'id' : 'harmonyContainer'})
    
    content = ''
    for paragraph in div.find_all('p'):
        content += paragraph.get_text()
        
    return content

news1 = get_news_content('https://news.v.daum.net/v/20210706141605093')
print(news1)
분산서비스거부(DDos·디도스)공격이 발생할 경우 대기업은 탐지까지 3분, 중소기업은 9분이 걸리는 것으로 나타났다. 해킹 메일도 25.8%가 열람하고 7.6%가 감염될 정도로 사이버 보안에 허술하다는 결과가 나왔다.과학기술정보통신부는 한국인터넷진흥원(KISA)과 함께 상반기 사이버위기 대응 모의훈련을 실시한 결과를 6일 발표했다. 5월 17일부터 2주간 실시한 이번 상반기 사이버위기 대응 모의훈련에는 230개 기업이 참여했다.디도스 모의공격에 대한 대응력 훈련 결과 대기업은 평균 디도스 공격 탐지시간 3분, 대응시간 19분 걸렸다. 중소기업은 평균 탐지시간이 9분, 대응시간은 22분이나 걸렸다.기업의 정보시스템에 대한 모의침투 훈련 결과 30개사 홈페이지에서 114개 취약점이 확인됐다. 클라우드 사업자를 대상으로 한 모의침투 훈련에서는 클라우드 보안 인증을 받은 사업자의 탐지 및 방어율이 미인증 사업자에 비해 높았다고 과기정통부는 전했다.시스템과 데이터를 잠근 뒤 이를 인질 삼아 금전을 요구하는 랜섬웨어 공격은 상반기에만 2019년도 전체 건수의 2배에 달할 정도로 급증했다. 랜섬웨어 공격은 2019년 39건에서 지난해 127건으로 225% 급증한 데 이어 올해 상반기에만 78건이 발생했다.과기정통부는 “랜섬웨어 침해사고 대부분이 이용자가 일반적 보안 수칙을 준수하지 않아 발생했다”며 “사용자 보안 인식 제고가 절실히 요구된다”고 강조했다. 과기정통부는 랜섬웨어 급증에 따라 특화 모의훈련을 개발하고 올해 10월 중 훈련을 실시할 예정이다.세종 류찬희 선임기자 chani@seoul.co.krCopyrightsⓒ 서울신문사. 무단 전재 및 재배포 금지 

스크롤링한 뉴스에서 위에서 compile한 이메일 주소 찾기 불러와서 사용

1
2
email_reg = re.compile(r'[\w-]+@[\w.]+\w+')
email_reg.search(news1)
<re.Match object; span=(773, 800), match='chani@seoul.co.krCopyrights'>

웹페이지 리스트에서 올바른 (http, https) 웹페이지만 찾기

1
2
3
4
5
6
7
8
webs = ['http://www.test.co.kr', 
        'https://www.test1.com', 
        'http://www.test.com', 
        'ftp://www.test.com', 
        'http:://www.test.com',
       'htp://www.test.com',
       'http://www.google.com', 
       'https://www.homepage.com.']

웹페이지를 찾는 정규표현식을 complie로 생성

1
web_reg = re.compile(r'https?://[\w.]+\w+$') # s? 를 붙임으로 http 와 https 둘다 포함해서 검색하도록 설정

lambda와 mapping을 활용해 생성한 정규표현식으로 웹페이지 찾기

  • list를 loop 하면서 T/F로 list화 해서 출력해주는 형식

  • web_reg의 결과가 None이면 False

1
list(map(lambda w:web_reg.search(w) != None, webs))
[True, True, True, False, False, False, True, False]

댓글남기기