3월, 2018의 게시물 표시

(Aws) SSH키페어를 이용한 계정관리

SSH키페어는 ssh-keygen이라는 프로그램으로 만들 수 있다. 내 PC의 이름이 my-pc이고 접근하려는 서버의 이름이 remote-pc라고 가정하자. 다음과 같이 rsa키를 만들 수 있다. 예) my-pc # ssh-keygen -t rsa Generating public/private rsa key pair. Enter file in which to save the key (/home/aaa/.ssh/id_rsa) : remote-pc Enter passphrase (empty for no passphrase) 다음과 같이 실행하면 작업 디렉토리에 remote-pc와 remote-pc.pub 파일이 생긴다. remote-pc가 개인키이고, remote-pc.pub이 공용키이다. 이 공용키를 접근하려는 운영체제의 유저 홈 디렉토리에 복사하면된다. remote-pc에 test라는 계정으로 접근하고 싶으면 test계정을 만든 다음 .ssh디렉토리에 authorize_keys파일을 만들고 여기에 id_rsa.pub파일의 내용을 추가하면된다. remote-pc # adduser test remote-pc # cd /home/test remote-pc # mkdir .ssh remote-pc # cat remote-pc.pub >> ./ssh/authorized_keys 이제 개인키 파일을 이용해서 remote-pc에 접근 할 수 있다. remote-pc # ssh -i remote-pc test@remote-pc

(Linux) top 명령어 설명

PID : 프로세스 ID USER : 프로세스 소유자 PR : 프로세스 우선순위 NI : 우선순위를 지정하는 Nice값 VIRT : 프로세스가 점유하는 가상메모리양 (KB단위) RES : 스왑되지 않은 물리메모리양 (KB단위) SHR : 공유되지 않은 공유메모리양 (KB단위) %MEM : 메모리 점유율 %CPU : CPU점유율

(Linux) ps -aux와 top명령어

ps -aux 명령어는 프로세스들의 정보를 보여주며 CPU사용량도 확인가능 top는 실시간 CPU사용량을 볼 수 있다. * ps 는 개별 프로세스의 상태를 보여주는데 반해 top는 전체적인 프로세스 상태를 알아 볼 때 사용가능하다.

(Linux) root 계정으로 다른 사용자 계정 비밀번호 바꾸기

$  sudo passwd [해당 계정]

(Linux) rsync 명령어

1.  파일 전송 결정 기본적으로 rsync는 파일의 크기와 수정시간을 비교하는 것으로 파일을 전송할지 말지를 결정한다. 이 방법은 아주 적은 CPU자원을 소모하지만 실수가 발생할 수 있다. 일반적으로 파일의 내용을 변경하면 크기와 수정시간이 변하지만 항상 그렇다고 단정할 수는 없기 때문이다. --checksum 옵션을 이용하면 비교방법을 개선할 수 있다. 이 옵션을 켜면, 파일의 checksum을 비교한다. 크기/시간을 이용한 비교방법보다 안전하지만 더 느리고 더 많은 자원을 사용한다. 2. 전송할 파일 부분 결정 파일 전송을 결정했다고 가정하자. 파일을 전송하기 위한 간단한 방법은 "전체 파일을 그대로 복사"하는 것이다. 쉬운 방법이지만 파일의 크기가 경우 효율적이지 않다. 1G 크기의 파일이 있다고 보자. 여기서 바뀐부분은 1k라고할때, 1k때문에 1G를 복사하게 될 것이다. Rsync는 파일의 변경된 부분만 효과적으로 복사하기 위한 알고리즘을 가지고 있다. Rsync는 파일을 고정 크기를 가지는 청크(chunk) 로 나눈다음에 checksum을 계산한다. 이 checksum을 서로 계산해서, 다를 경우 해당 부분의 청크만을 복사한다. 만약 파일의 앞 부분의 정보가 수정돼서 정보들이 밀린다면 모든 청크의 checksum이 어긋날것이다. 이 문제를 피하기 위해서 "Rollish hash"를 사용한다. 1. 로컬 컴퓨터에서 파일과 디렉토리 복사 및 동기화 #aaa.tar파일을 /var/user 디렉토리로 복사 $ rsync -avzh aaa.tar /var/user #wiki 디렉토리를 /var/user 디렉토리로 복사 $rsync -avzh wiki/ /var/user

(Linux) 특정 계정을 새로운 그룹에 포함시키기 (usermod)

sudo usermod -aG docker $(whoami)

(Linux) systemctl 명령어

* 서비스 상태 확인하기  $ systemctl status {servicename} * 서비스 시작, 중지, 재시작 하기 $ systemctl start {serviceName} $ systemctl stop {serviceName} $ systemctl restart {serviceName} * 부팅 후 서비스 활성화 비활성화 $ systemctl enable {serviceName} $ systemctl disable {serviceName} * 서비스 제거/등록 $ systemctl mask {serviceName} $ systemctl unmask {serviceName} * 실행 중인 서비스 보기 $ systemctl list-units -type=service $ systemctl list-unit-files | grep enabled

(Linux) 리눅스 파일권한

리눅스 파일 권한은 읽기 (read), 쓰기 (write), 실행 (execute) 이다.  읽기 : 보여지는 파일의 컨텐츠를 읽을 수 있는 권한. 디렉토리에 대한 읽기 권한은 디렉토리의 컨텐츠 항목 들을 볼 수 있게 해준다.  쓰기 : 파일에 대한 쓰기 권한은 파일의 컨텐츠를 변경할 수 있게 해준다. 디렉토리의 경우 쓰기 권한은 디렉토리 컨텐츠를 편집할 수 있게 해준다. (파일의 추가/삭제)  실행 : 파일의 경우 실행 권한은 파일을 실행하거나 프로그램이나 스크립트를 실행할 수 있게 해준다. 디렉토리의 경우 실행 권한은 다른 디렉토리로 변경하거나 그것을 현재 작업 디렉토리로 만들 수 있게 해준다. 사용자는 보통 디폴트 그룹을 가지고 있으나 여러 추가적인 그룹에도 속할 수 있다. <파일 권한 보기> 파일이나 디렉토리 권한을 보려면, ls -l [directory/file] 명령어를 사용하라. 또는 ls -al 은 현재 디렉토리에 속해있는 파일 전체의 권한을 볼 수 있다. 예제)  drwx------ 2 docker docker 4096 Mar 25 03:39 .ssh 처음 10개의 문자가 접근 권한을 보여준다. 첫 번째 대시(-)는 파일의 형식을 보여준다 (d는 디렉토리, s는 특별 파일, -는 보통파일) 그 다음 세 문자(rwx)는 파일의 소유자에 대한 권한을 정의한다. 즉, 파일소유자는 읽기, 쓰기, 실행이 가능하다. 그 다음 세문자 (---)는 파일의 소유자와 같은 그룹에 속한 멤버에 대한 권한이다. 이 예제에서는 읽기, 쓰기, 실행이 불가능하다. 그 다음 세 문자는 다른 모든 사용자에대한 권한을 표시한다. 역시 읽기, 쓰기, 실행이 불가능하다. 즉 이 디렉토리는 파일소유자만 읽기, 쓰기, 실행이 가능하다. 그 다음 숫자 2는 해당 파일 또는 디렉토리에 속해있는 파일, 디렉토리의 수이다. 그 다음 docker는 파일 소유자의 이름, 그 다음 docker는 파일 소유자의 그룹 이

(Aws) Network ACL vs Security group의 차이점

Network ACL의 경우 네트워크 레벨에서의 방화벽 이라면, Security Group 는 인스턴스 레벨의 방화벽이라고 생각하면 된다.

(Alogrithm) Binary Search Tree Iterable

with Binary Search Tree, To require O(1) average Time(amortized analysis) and O(h) space. O(h) 공간을 만족하기 위해서, 루트 노드의 왼쪽값만 저장한다. 그 후 next()값을 호출시, 방금 출력된 값보다 큰 root.right를 삽입하여 O(h) 공간을 만족시킨다. Stack<TreeNode> treeList; public BinarySearchIterable(TreeNode root) {     while(root != null) {         treeList.push(root);         root = root.left;     }   }  public boolean hasNext() {       if(treeList.isEmpty())           return false;     return true;   }  public int next() {       if(hasNext()) {           TreeNode n = treeList.pop();           int value = n.value;           treeList.push(n.right);       }   }

(ElasticSearch) 복합 검색 (Bool Query)

bool 쿼리의 must는 반드시 검색하려는 term이 도큐먼트에 포함되어야만 하는 조건을 만들고, should는 조건 속성에 따라 다르지만 최소 하나 이상의 term이 포함된 문서를 검색하는 조건을 만든다. 즉, must는 AND조건을 만들고 should는 OR조건을 만든다고 이해하면 된다. <must 예제> {  "query" : {     "bool" : {       "must" : {          { "terms" : {              "unified_search" : [                   삼성, TV               ],            "minimum_match" : 2          }        }     }   } }

(ElasticSearch) Match All Query, Range Query

이 쿼리는 SELECT * FROM TABLE , SQL 문자열처럼 모든 도큐먼트를 구해오는 쿼리다. 검색 서비스에서는 거의 사용하지 않고, 보통 관리 목적으로 사용한다. {   "query" : {     "match_all" : {}    } } term 쿼리와 비슷하게 가장 많이 사용하는 쿼리로, number와 date, ip등의 데이터형을 갖는 필드에 대한 범위를 지정하여 도큐먼트를 검색한다. 필드 특성은 인덱스 속성을 not_analyzed로 설정해야 한다. 다음은 상품판매 가격에대한 range쿼리로 상품가격이 100만원보다 크거나 같고 150만원보다 작거나 같은 상품 검색을 한다. curl -XGET "http://localhost:9200/open_market/_search" -d {    "query" : {       "range" : {              "item_sales_price" : {                "gte" : 1000000,                "lte" : 1500000              }          }      } }

(ElasticSearch) Prefix Query

이 쿼리는 텍스트의 앞 문자열에 대한 term의 일치 여부에 따라 검색 결과를 가져온다. prefix쿼리를 이용하면 자동완성 기능을 쉽게 구혀 할 수 있다. 이 쿼리에 대한 검색 대상 필드는 인덱스 속성이 not_analyzed로 설정되어야 하고, 다른 속성 값을 가진 필드로 검색을 실행하면 잘못된 결과가 나오게 된다.

(ElasticSearch) index mapping analyzed 차이점

1. analyzed 인경우 형태소 분석을 한다. 2. not_analyzed는 단순 검색만 가능하다. 3. no는 형태소분석, 단순 검색도 불가능하고 출력만 가능하다. * name필드를 형태소 분석하는 경우 {   "name" : {       "type" : "string",       "index" : "analyzed"     } } * name필드를 단순 검색만 하는 경우 {  "name" : {      "type" : "string",      "index" : "not_analyzed"    } } * name필드를 단순 출력만 하는 경우 {   "name" : {       "type" : "string",      "index" : "no"      } }

(ElasticSearch) Identifiers Query

도큐먼트의 Primary 또는 유니크 키에 해당하는 값을 이용해서 검색하는 쿼리로 _id필드에 도큐먼트 id목록을 요청하여 도큐먼트 정보를 구한다. _id 필드는 인덱스 속성을 not_analyzed로 해야한다는 것에 주의하자. 이 쿼리는 일반적으로 도큐먼트 정보를 빠르게 검색하여 상세페이지를 구성하는 데 유용하게 사용된다. curl -XGET "http://localhost:9200/open_market/_search" -d' {   "query" : {       "ids" : {          "type" : "market",           "values" : [3, 5]        }     } }'

알고리즘 자료구조 분류

* 힙 * 이진탐색트리 * 이진트리 * Trie * 링크드리스트 * String 문자열 매칭 * 네트워크 유량 1. 포드 풀커슨 알고리즘 2. 최소컷 알고리즘 <운영체제 알고리즘> * Cache 알고리즘 1. LRU 알고리즘 * CPU 스케줄링 알고리즘 1. 선점형 스케줄링 -> SRT알고리즘 2. 비선점형 스케줄링 -> SJF알고리즘 -> FCFS알고리즘

(Docker) Docker run명령어

다음은 이미지로 컨테이너를 생성하는 run명령어이다. docker run <옵션> <이미지 이름, ID> <명령> <매개변수> 옵션에 값을 설정할때는 =와 "는 생략 가능하다. 1. -a, --attach=[] : 컨테이너에 표준 입력(stdin), 표준 출력(stdout), 표준에러(stderr)를 연결한다. 예) --attach="stdin" 2. -add-hosts=[]: 컨테이너의 /etc/hosts에 호스트 이름과 IP주소를 추가한다. 예) --add-hosts=hello:192.168.0.10 3. -c, --cpu-shares=0: CPU자원 분배 설정이다. 설정의 기본값은 1024이며 각 값은 상대적으로 적용된다. 예) --cpu-shares=2048 처럼 설정하면 기본 값보다 두 배 많은 CPU자원을 할당한다. 이 설정값은 리눅스 커널의 cgroups에서 사용한다. 4. --cap-add=[]: 컨테이너에서 cgroups의 특정 Capability를 사용한다. ALL을 지정하면 모든 Capability를 사용한다. 5. -- cap-drop=[]: 컨테이너에서 cgroups의 특정 Capability를 제외한다. 6. --cidfile="" : cid파일 경로를 설정합니다. cid파일에는 생성된 컨테이너의 ID가 저장된다. 7. --cpuset="" : 멀티코어 CPU에서 컨테이너가 실행될 코어를 설정한다. 예) --cpuset="0,1" 처럼 설정하면 첫, 두번째 CPU코어를 설정한다. 예) --cpuset="0-3" 처럼 설정하면 첫번째에서 네 번쨰 CPU코어까지 사용한다. 8. d, --detach=[]: Detached모드이다. 보통 데몬 모드라 부르고, 컨테이너가 백그라운드로 실행된다. 9. --device=[] : 호스트의 장치를 컨테이너에서 사

(Docker) Docker inspect 명령어

inspect 명령어는 컨테이너와 이미지의 세부 정보를 JSON 형태로 출력하는 inspect 명령입니다. * docker inspect <옵션> <컨테이너 또는 이미지 이름, ID> > -f , --format="":  지정한 정보만 출력합니다. 예) "{{.NetworkSettings.IPAddress}}" 처럼 .(점) 으로 JSON 문서의 하위 항목을 설정 할 수 있습니다. 1. 다음 명령은 이미지 세부정보에서 아키텍처와 OS를 출력한다. $ sudo docker inspect -f "{{.Architecture}} {{.Os}}" ubuntu:16.04 2. 다음 명령은 컨테이너의 IP주소를 출력합니다. $ sudo docker run -i -t -d --name hello ubuntu:16.04 /bin/bash $ sudo docker inspect -f ""{{.NetworkSettings.IPAddress}} hello 3. 다음 명령은 컨테이너의 세부 정보에서 특정 부분만 추출하여 원하는 포맷으로 출력한다. $sudo docker run -i -t -d --name hello -p 80:80 -p 8080:8080 ubuntu:14.04 /bin/bash $sudo docker inspect -f '{{range $p, $conf := .NetworkSettings.ports}} {{$p}} -> {{(index $conf 0).HostPort}} {{end}}' hello 여기서 {{range $p, $conf := .NetworkSettings.Ports}} 으로 .NetworkSettings.Ports의 내용을 순회하면서 $p, $conf에 대입합니다. 그리고 $p는 그대로 출력하고, $conf 배열에서 첫 번째 항목(index $conf0)의 .HostPort를 출력합니다.

(Docker) Container와 Images의 차이

Container는 read-write가 가능한 레이어이고, image 는 오로지 read-only만 가능한 레이어이다. 또한, Container는 항상 최상단에 위치한다. Container에 수정한 정보를 재사용하고 싶다면 docker commit을 통해 images로 만들어야 한다.

(Docker) 다른 서버의 Docker 컨테이너에 연결하기

--link 옵션은  같은 서버의 컨테이너끼리 연결하는 옵션이다 그러나 엠베서더 컨테이너 라는 것을 이용하면 다른 서버에 있는 컨테이너에 연결할 수 있다.

(Docker) Docker 컨테이너 연결하기

Docker로 이미지를 생성할 때, 웹 서버, DB 등 필요한 프로그램을 모두 설치할 수도 있지만 보통 프로그램별로 이미지를 생성합니다. 이렇게 프로그램 별로 이미지를 생성하고, 컨테이너를 생성했을 때 옆에 있는 컨테이너에 접속할 일이 많습니다. 예를 들면, 웹 서버는 DB에 연결하여 데이터를 주고 받아야 합니다. web 컨테이너 (Ngingx) ---------> db컨테이너 (mongodb(db:27017)) Docker 컨테이너끼리 연결할 때는 docker run 명령에서 --link옵션을 사용한다. 먼저 DB이미지를 컨테이너로 실행합니다. 이번예제는 MongoDB를 사용하는 예지이다. $ sudo docker run --name mongodb -d mongo db컨테이너 이름은 mongodb이다. $ sudo docker run --name web -d -p 80:80 --link mongodb:mongodb nginx web 컨테이너를 생성하면서 db 컨테이너를 mongodb 컨테이너와 연결합니다. docker run 명령어에서 연결 옵션은 --link <컨테이너이름>: <별칭> 형식입니다. * 별칭과 IP 주소 docker inspect 명령으로 web 컨테이너의 세부 정보에서 hosts 파일 경로를 구한 뒤 cat 명령으로 내용을 살펴 볼 수 있다. $ cat 'sudo docker inspect -f "{{.HostsPath}}" web'

(Docker) 개인저장소 구축(Registry 서버)

1.  태그 생성하기 $sudo docker tag hello:0.1 localhost:5000/hello:0.1 => docker tag <이미지 이름>:<태그> <Docker 레지스트리 Url>/<이미지 이름>:<태그> 2. 이미지 올리는 명령어 $ sudo  docker push localhost:5000/hello:0.1 => 이미지 올리는 명령어는 docker push <Docker 레지스트리 Url>:<이미지 이름>:<태그> 이다 *  개인 저장소에 이미지를 올릴 때에는 먼저 태그를 생성해야 한다.

(Docker) Docker 주요명령어

1. history 명령으로 이미지 히스토리 살펴보기 $ sudo docker history hello:0.1 => docker history <이미지이름>:<태그> 형식 이미지 이름 대신 이미지 ID 를 사용해도 괜찮음. 2. cp 명령으로 파일 꺼내기 $ sudo docker cp hello-nginx:/etc/nginx/nginx.conf ./ => docker cp <컨테이너 이름>:<경로> <호스트경로> 형식이다. 현재 디렉토리에 nginx.conf 파일이 복사된다. 3. commit 명령으로 컨테이너의 변경사항을 이미지로 생성하기 docker commit 명령은 컨테이너의 변경 사항을 이미지 파일로 생성한다. hello-nginx 컨테이너 안의 파일 내용이 바뀌었다고 치고,  컨테이너를 이미지 파일로 생성합니다 $ sudo docker commit -a "Foo Bar <foo@bar.com>" -m "add hello.txt" hello-nginx hello:0.2 => -a "Foo Bar <foo@bar.com>" -m "add hello.txt"  옵션으로  커밋한 사용자와 로그메시지를 설정합니다. * --author, -a : 이미지 생성하는 Author * --change, -c :  Apply Dockerfile instruction to the created image * --commit, -c : Commit message * --pause , -p : pause container during commit 4. diff 명령으로 컨테이너에서 변경된 파일 확인하기 $ sudo docker diff hello-nginx => 컨테이너가 실행되면서 변경된 파일 목록을 출력합니다. => docker diff

(Docker) 도커 주요 명령어

1.  이미지 검색하기 -> ubuntu 이미지 검색 $ sudo docker search ubuntu 2. pull 명령으로 이미지 받기 $ sudo docker pull ubuntu:latest 3. images 명령으로 이미지 목록 출력하기 $ sudo docker images 4. run 명령으로 컨테이너 생성하기 $ sudo docker run -i -t --name hello ubuntu /bin/bash -> -i , -t  옵션을 사용하면 실행된 Bash셸에 입력 및 출력을 할 수 있습니다. 5. ps명령으로 컨테이너 목록 확인하기 $ sudo docker ps -a -a 옵션을 사용하면 정지된 컨테이너까지 모두 출력하고, 옵션을 사용하지 않으면 실행되고 있는 컨테이너만 출력한다 6. start 명령으로 컨테이너 시작하기 $ sudo docker start hello 7. restart 명령으로 컨테이너 재시작하기 $ sudo docker restart hello 8. attach 명령으로  컨테이너 접속하기 $ sudo docker attach hello DB나 서버 애플리케이션에서느 실행하면 입력은 할 수 없고, 출력만 가능하다. Bash셸에서 exit나 Ctrl + D 를 입력하면 컨테이너가 정지되고, Ctrl + P, Ctrl + Q를 입력하면 컨테이너를 정지하지 않고, 컨테이너에서 빠져나온다. 9. exec명령으로  외부에서 컨테이너 안의 명령 실행하기 $sudo docker exec hello echo "Hello World" 10 .stop 명령으로  컨테이너 정지하기 $ sudo docker stop hello 11. rm명령으로 컨테이너 삭제하기 $sudo docker rm hello 12. rmi 명령으로 이미지 삭제하기 $sudo docker rmi ubuntu:latest

(Python) 장고에서 객체를 문자열로 표현하기

장고에서 객체를 문자열로 표현하기 위해서, 파이썬 버전에 따라 다른 메소드를 사용합니다. 즉, 파이썬 2에서는 __unicode__() 메소드를, 파이썬 3에서는 __str__() 메소드를 사용합니다. 장고는 개발자의 편의를 위해 또 다른 방법을 제공합니다. 즉 파이썬 버전에 무관하게 하나의 메소드만 사용하게 하는 방식입니다. 1. 클래스 정의에 @python_2_unicode_compatible 데코레이터를 적용합니다. 2. 파이썬 3문법인 __str__() 메소드만을 사용합니다. (파이썬 2환경에서는 장고가 알아서 변환)

(MongoDB) 복합인덱스 사용시 중요한점

다음가 같은 예가 있다. 인덱스는 db.collection("users").ensureIndex({"age" : 1, "username" : 1}) db.collection("users").ensureIndex({"username" : 1, "age" : 1}) 두개가 있다. 다음 두 조건으로 검색한다고 하면, 1 . db.collections("users").find({"age" : {"$gte" : 21, "$lte" : 30}})  .sort({"usernmae" : 1})  .limit(1000) .hint({"age": 1, "username" : 1}) .explain() 2. db.collections("users").find({"age" : {"$gte" : 21, "$lte" : 30}})  .sort({"usernmae" : 1})  .limit(1000) .hint({"username": 1, "age" : 1}) .explain() - > 어느것이 더 성능이 좋을까? 2 번이 더 성능이 좋다? 인덱스는 앞의 키부터 타기 때문에 1번이 좋다고 생각 할 수 있지만, 인덱의 정렬순서는 왼쪽 최말단이 가장 작은 값이,  오른쪽 최말단 리프에 가장 큰 값이 들어가는 트리구조다 기본적으로 시간에 따라 탐색하기 때문이다. 즉, {"정렬키" : 1, "쿼리 검색 조건" : 1} 형태의 인덱스 조건이 애플리케이션에서 대체로 잘 동작한다. 따라서 오래된 데이터보다 최신의 데이터를 사용하는 경향이 있는 애플

(Algorithm) B tree 설명 및 pseudo-code

B-Tree는 self-balancing 탐색 트리로. 거의 모든 데이터가 메모리상에 존재한다고 보면된다. 그러나 데이터량이 커지면 이 모든 것을 메인 메모리에 보관할 수 없다. 만약 key의 숫자가 커질 수록, 데이터들은 디스크에서 정보를 가져올 수 밖에 없다. 디스크 액세스 타임의 비용은 메인메모리 액세스 타임보다 훨씬 비용이 크다. B-Tree의 핵심은 디스크 액세스타임을 감소 시키는 것이 목적이다. B-Tree의 높이 h는 디스크 접근의 횟수와 비례한다 즉, 이것에 따라 성능이 결정된다. B-Tree의 PseudoCode는 다음과 같다. 1. B트리의 검색 (B-Tree-Search) 2. 빈 트리 생성 (B-Tree-Create) 3. B트리에 삽입 (B-Tree-Insert) 4. B트리 분할 (B-Tree-Split) 1. B트리의 검색 (B-Tree-Search) B-Tree-Search (x, k)  // x is node, k is value what we find. i = 1 while i<= x.n && k > x.key(i)  i= i + 1 if i <= x.n && k == x.key(i)  return (x, i) // x is node , i is index number else if x. leaf  return nil else DISK-READ(x)  return B-Tree-Search(x, k) 2. 빈 트리 생성 (B-Tree-Create) B-Tree-Create (T) x = new Node() x.leaf = true x.n = 0 (X노드에 있는 값의 갯수 0) Disk-Write(x) T.Root = x 3. B트리에 삽입 (B-Tree-Insert) O(h)번의 디스크 접근과 , O(tlogN)의 CPU시간이 걸린다. B-Tree-Inser

(Python) XPath Grammer

XPath is "(XML Path)" of abbreviation. This is query language that explore and select some part of XML document. In 1999, W3C make this and it is used in Java, Pytho, C# Unfortunately BeatifulSoup isn`t supported this XPath library. The XPath usage is similar with usage of CSS selector.(like my#idname) It is consist of four concept root node vs non root node -  /div is only choosing root div node in a document. - //div is every div node in a document choice attriute - //@href is choosing all href attribute node  ex) //a[@href='http://google.com] is choosing all node which is indicated to "google.com" in a document choice node according to location - (//a)[3] is choosing third link in a document. - (//table)[last()] is choosing last table in a document. - (//a)[position()<3] is choosing first and second link in a document. asterik(*) is every character node set, this is useful in every situation. - //table/tr/*

(python) selenium selector (multi elements)

There is scrapable library "BeautifulSoup" Selenium is almost same with "BeautifulSoup" but the difference is that Selenium can "DOM" attrubute in dynamic wep page. I will show you some example. ex) 1. driver.find_element_by_css_selector("#content") 2. driver.find_element_by_tag_name("div") If you have to select multi attribute not a single. you can use "elements" ( append character "s" above element of two example) the result value type is "LIST" ex) 1. driver.find_elements_by_css_selector("#content) 2. driver.find_elements_by_css_selector("div")