목차

반응형

오디오에 대하여 프로그래밍 하려고 함.

최종적인 목표는 C#으로 게임 OST같이 한번에 많은 음악파일들을 하나의 음악파일로 합쳐놨을때 공백을 구분하여 따로따로 분리해주는 프로그램을 만드는 것.

반응형

'C# > C#' 카테고리의 다른 글

C# 한양대학교 학식 크롤링 프로그램  (0) 2016.03.02
C# 콘솔 Output 보기  (0) 2016.02.24
C# 네이버 웹툰 크롤링 프로그램  (1) 2015.11.16
반응형

hsb.exe


학식 보는 프로그램을 만든다. 일단 C#에서 만들고 안드로이드에서도 만들예정.


저번에 웹툰프로그램 만들면서 html페이지를 전부다 불러오고 특정 코드앞에서 받아오는 형태의 노가다로 파싱해왔는데 html agility pack을 이용해서 효울적으로 만들 수 있었다.

앞으로는 이것을 이용해서 할 생각

1. agility pack을 이용한다.

http://stackoverflow.com/questions/846994/how-to-use-html-agility-pack

대충 정리해놓자면

foreach (HtmlNode table in doc.DocumentNode.SelectNodes("//table[@summary='식당정보']"))

label.text += table.InnerText;

라고 한다면 doc의 html 코드중 summary 속성값이 식당정보인 모든 테이블을 가져오고 그 아래의 반복문은 해당테이블의 텍스트값을 라벨에 누적해서 넣는것.

즉 모든테이블의 텍스트가 라벨로 들어가게 된다.


-----설치방법------

Visual 스튜디오에서 프로젝트 우클릭후 Manage Nuget Packages로 들어가서 HtmlAgilityPack을 설치.

agility pack은 xpath를 사용하는데 

http://www.w3schools.com/xsl/xpath_examples.asp

여기서 대강 사용법을 알 수 있다. 나중에 정독 예정.

정독해보았는데 //와 /의 사용법만 알아두면 충분한것같다.


일단 야매로 대충 어떤 테이블의 첫 td 값이 중식/석식 일때 그때 2번째 테이블의 값을 알아오는 기능을 구현하였다.

그런데 인코딩문제인지 먼지 계속 외계어로 떠서 인식이 불가능함 현재 연구중...

그 원인을 찾았다. 계속 utf-8로 인코딩했는데 알고보니까 학식페이지 가보면 utf-8이 아니고 euc-kr로 되어있음.

http://stackoverflow.com/questions/14793650/wrong-encoding-with-html-agility-pack

위의 사이트를 들어가면 페이지가 euc-kr로 인코딩 되어있을때 문서 불러오는 방법 나와있음.


구현해야 하는 것들


총 6개의 식당 -> 6개의 Tab

일단 tabcontrol을 사용하여 6개의 식당 탭을 만들었다. 각 탭의 라벨이라던가 버튼의 내용물은 for문을 사용하여 동적 생성함.

여기서 한가지 알아낸점은

첫번째 탭컨트롤에 버튼을 추가하고 두번째 탭컨트롤에 버튼을 추가하는식으로 for문을 돌려서 컨트롤을 추가해야지 탭페이지에 나타나는데

요소는 tabPage1, tabPage2, tabPage3 ... 이라서 for문으로 각 tabPage를 호출하는 방법이 없다.

그러나 tabControl1.TabPages[i].Controls.Add(panels[i, j]); 를 사용하여 각각의 tabPage를 호출하는 방법이 있다.

또한 각각의 탭에는 날짜의 개수만큼의 패널을 동적으로 생성하여 집어넣었다.

1번식당tab

월요일 패널

버튼,버튼,라벨

화요일 패널

버튼,버튼,라벨

.

.

.

토요일 패널

버튼,버튼,라벨

이런형식이다.



각각의 식당마다 월~토 운영하는 날의 개수가 다름

친구에게 물어보았다.

각 1번식당은 금요일까지만 운영하고 2번식당은 토요일까지 운영하는데 이것을 알고있으니까 1번테이블만 5일치 받아오고 2번식당만 6일치 받아오는것이 나은가?

아니면 요일개수를 카운트하는 기능을 넣는것이 나은가?

친구말로는 나중에 바뀔때 수정하기가 귀찮으므로 이럴때는 그냥 카운트하는 기능을 추가하는 것이 맞다고 하였다.

그래서 식당의 개수가 몇개인지 카운트하는 기능을 넣었다.

함수명은 check_number_of_days();

html 코드를 보니까 요일명이 들어가는 td는 테이블 헤더로 해놓았다. 따라서 모든 th의 텍스트중 요일이 들어가는 경우 해당 식당의 날짜개수 카운트를 ++해준다.

예로 2번식당에는 토요일까지 운영하면 월요일, 화요일..., 토요일까지 테이블에 표기가 되므로 위의 코드에 의하여 6이된다.



메뉴 개수가 식당마다 다름

이것은 어떻게 할지 고민했는데 아래에 메뉴표기기능에서 알아서 해결됨.



메뉴의 가격 보여줘야함

이것도 어떻게할지 고민했는데 메뉴표기기능에서 해결함.


운영안하는 날

1번식당은 토요일날 운영을 안하는데 사용자가 토요일로 가면 어떻게 표기할지.

각 식당마다 운영정보 없음을 나타내는 패널을 하나씩 만든다음 운영정보가 없는 날에는 해당 패널을 보여주도록 함.


날짜 표기

오늘 날짜 알려주는 기능과 요일까지 표시해주는 기능.

today = (int)(ClockInfoFromSystem.DayOfWeek + 6) % 7; // 월요일 0 화요일 1 수요일 2 ... 일요일 6 으로 표기되도록함.

label = 오늘 날짜 + (스위치문 위의 today값이 2면 '수'를 붙임, 3이면 '목'을 붙임)

이런형식


날짜 넘어가는 기능

today를 위의 코드로 알맞은 인덱스 값으로 초기화시켜놓고 앞으로가기 버튼을 누르면 1추가 뒤로가기 누르면 1감소

만약 6을 넘어가버리면 다시 0으로 가는 형식.

그리고 인덱스에 해당하는 패널을 보여준다.


move_pre_panel()도 비슷함.

아 헷갈린것은 datetime++; 이아니고 datetime=datetime.AddDays(1);을 해줘야 한다는 점.

now_day는 today를 받아온것이다.



괄호로 영어로 표기된부분 없애자 -> 아직 미구현 구현해야함

영어로 표기해놓은 것은 쓸모없고 자리만 차지해서 없애야한다.


고정된 폼크기

http://ndolson.com/1552

http://stackoverflow.com/questions/13381127/preventing-winform-from-being-maximized



메뉴 보여주기(제일 중요함, 제일 어려움)

제일 어려운 부분이다.

시작하자마자 어디서부터 시작할지 막막했다.


무엇을 탐색하나?

공통 간식 여부

공통찬 여부

아침 점심 저녁인지 점심 저녁인지 여부

월화수목금토인지 월화수목금인지 여부

교직원식당 학생식당 구분 여부


식당정보는 summary 속성의 값이 식당정보다

즉 테이블중 summary속성의 값이 식당정보인 것의 테이블 소스를 가져와서 보여주자.


애초에 html agility pack에 테이블을 가져오는 튜토리얼이 있음

http://stackoverflow.com/questions/9265313/parsing-html-with-htmlagilitypack-and-loading-into-datatable-c-sharp

http://stackoverflow.com/questions/655603/html-agility-pack-parsing-tables


LINQ-to-Objects 라는 되게 손쉬운 방법이 있는듯함

나중에 사용하여 구현해보자


c# 테이블 사용방법


foreach (HtmlNode table in doc.DocumentNode.SelectNodes("//table[@summary='식당정보']"))

                {

                    label2.Text += "Found: " + table.Attributes["summary"].Value + "\n";

                    foreach (HtmlNode row in table.SelectNodes("tr"))

                    {

                        foreach (HtmlNode cell in row.SelectNodes("th|td"))

                        {

                            label3.Text += "\n"+cell.InnerText;

                        }

                    }


                }

에서 왜 foreach (HtmlNode row in table.SelectNodes("tr")) tr이 //tr로하면 모든 tr을 다받아오나? // 그냥 foreach문이 그런것



요일몇개까지있나 확인은 if(ths.InnerText.Contains("요일")) 이것으로 요일 들어가는 문자열개수를 카운트함.


http://stackoverflow.com/questions/9199080/how-to-get-the-integer-value-of-day-of-week

                            labels[i].Text += "\n" + cell.InnerText.Replace(" ", "");

로 원하지않는 문자열 필터링 가능


갑자기 html agility pack 사용중 개체참조리퍼런스 에러가 뜸 해결법 찾는중

이유 : 테이블안에 tr 안에 td가 있으면 //table 하고 바로 td하면 안되고 tr/td 해야 먹힘 !!중요!!

안되는 이유 - 안에 <tr>이랑 \n이 있으면 널이 아님처리되서 그러니까


이제는 마지막 가격이 아래로 내려가부림;;

실행할때 dll파일없이 실행하려면  IlMerge를 사용

반응형

'C# > C#' 카테고리의 다른 글

C# - Audio Programmning  (1) 2016.04.25
C# 콘솔 Output 보기  (0) 2016.02.24
C# 네이버 웹툰 크롤링 프로그램  (1) 2015.11.16
반응형

C# 프로젝트 하위 덩어리 오른쪽 properties -> output type -> console application

반응형

'C# > C#' 카테고리의 다른 글

C# - Audio Programmning  (1) 2016.04.25
C# 한양대학교 학식 크롤링 프로그램  (0) 2016.03.02
C# 네이버 웹툰 크롤링 프로그램  (1) 2015.11.16
반응형




완성본


1. 네이버 웹툰에서 이미지를 다운받아오는 기능 구현

네이버에서는 단순히 donloadfileasync함수만으로 다운받으면 403 access denied 오류(피들러로 확인)를 받는다.

확인해본바로

wc.Headers.Add("user-agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");

wc.Headers.Add("Content-Type", "application / zip, application / octet - stream");

wc.Headers.Add("Accept-Encoding", "gzip,deflate,sdch");

wc.Headers.Add("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8");

wc.DownloadFileAsync(new Uri(remoteAddress), fileName);

와같은 함수로 request에 부가적인 내용을 전송해야 사용자로 인식하여 403에러를 안내놓는다고 하였다.

피들러로 정상적인 request와 비교하여 user-agent와 content-type accept-encoding accept를 추가하였으나 바뀌지않음

구글링하다가 wc.Headers.Add("Referer", "http://comic.naver.com/"); referer를 추가해보라는 말을 듣고 추가해보았음.

주소는 comic.naver.com request를 작동시키는데 성공함 (referer만 있어도 정상작동)

referer가 어떤것인지에대해서는 잘 모르겠음.

다만 찾아보니 이전에 있던 페이지에 대하여 나타내는 정보로 

referer가 comic.naver.com이면 이 요청은 comic.naver.com페이지에서 보내는 것이라는 정도...?

예로 http://imgcomic.naver.net/webtoon/119874/772/20151109162819_a6fdbf0fa4dc67716b370d99fd60e050_IMA

G01_5.jpg를 방문하면 이전에 있던 페이지가 없어서인지 403 오류가 뜸.


2. 이미지 개수 파악, 각 이미지 파일의 주소를 파악.

html 파일로부터 위에 해당하는 텍스트를 가져와야함.

예시 코드)) 

<img src="http://imgcomic.naver.net/webtoon/119874/772/20151109162819_a6fdbf0fa4dc67716b370d99fd60e050_

IMAG01_1.jpg" title="" alt="comic content" id="content_image_0" 

onerror="this.src='http://static.comic.naver.net/staticImages/COMICWEB/NAVER/img/common/blank.gif'" 

onload="loadImageEvent(this);" oncontextmenu="return false" ondragstart="return false" onselectstart="return 

false" class="">

이 코드에서는 http://imgcomic.naver.net/webtoon/119874/772/20151109162819_a6fdbf0fa4dc67716b370d99fd60e050_

IMAG01_1.jpg를 가져와야함.

이거하다가보니 2가지 방법을 찾았다.

i)agility pack(html 파싱할때 사용하는 도구?? 사용안해봐서 잘 모르겠음) 사용

ii)regex함수를 사용하여 약간 노가다식으로 구하기

http://www.csharpstudy.com/Practical/Prac-regex-1.aspx

http://www.csharpstudy.com/Practical/Prac-regex2.aspx

일부만 참고함.

agility pack은 어떻게 사용하는지 모르고 설치하는 방법도 몰라서 익숙한 regex를 사용하기로함.

일단 원하는 주소의 소스코드를 가져온뒤 스트링에다가 집어넣었음.

원하는 이미지는 항상 http://숫자.jpg" title="" alt="comic content" id="content_image_숫자" 식

따라서 해당부분을 regex를 사용하여 소스코드 스트링에서 싹다 찾아오기로함.

그과정에서 c#의 escaping 문자열에 대한 정보를 알게됨.

문자열을 나타낼때

string s = "asdsd"인데

asd"asd를 스트링으로 표현하려면

string s = "asd\"asd"으로 해야함.

대부분의 특수문자는 앞에 \를 붙여야함 \는 \\로

그리고 이게 귀찮아서 @를 붙일수가있음.

string s = @"asd\asd"하면 s에 asd\asd가 저장됨

단 예외로 "는 @를 붙이면 ""로 나타내고 ?는 \?로 나타내야함.

더많은 예외가 있겠지만 코딩하면서 위의 정보만 필요했음.

escaping in c#에 대한 정보글

http://www.codeproject.com/Articles/371232/Escaping-in-Csharp-characters-strings-string-forma 큰 도움되었음

또한 regex에서의 와일드카드를 사용한 검색방법에 대하여 알게됨.

요점만 말하자면 ^는 앞에서 시작하는 것 .*는 * ?는 .$로

예시 foo*.xls? will get transformed to ^foo.*\.xls.$

내가 찾고 싶은 것은 "http//로 시작해서 뒤에 주소가 붙고 title="" alt="comic content" id="content_image_숫자 형식이어야함


따라서 Regex regex = new Regex(@"http://.*"" title="""" alt=""comic content"" id=""content_image_");

를 하면 http부터 image_숫자 <- 숫자 전까지 긁어올 수 있음.

while (m.Success)

{

label1.Text+=m.Index + m.Value;

m = m.NextMatch();

}로 배열에 m.Value를 "로 스플릿하여 앞부분을 집어넣음으로써 모든 이미지 주소를 넣는다.

도중에 찾음.

메타문자 의미

------------------------

^ 라인의 처음

$ 라인의 마지막

\w 문자(영숫자) [a-zA-Z_0-9]

\s Whitespace (공백,뉴라인,탭..)

\d 숫자

* Zero 혹은 그 이상

+ 하나 이상

? Zero 혹은 하나

. Newline을 제외한 한 문자

[ ] 가능한 문자들

[^ ] 가능하지 않은 문자들

[ - ] 가능 문자 범위

{n,m} 최소 n개, 최대 m개

( ) 그룹

| 논리 OR


3. 파일명과 확장자를 받아오는데 이것이 개판이라서 확장자명을 알아내고 파일명도 AEFJFJAFAAWDJRHG.JPG가 아닌 보기좋게 나타내도록 함.

파일명은 후에 인덱스값을 이용하여 나타내고 확장자는 위와 같은 원리로 찾아냄.

만화 메인주소를 알려준다

4. 만화 목차페이지에서 각화의 주소를 가져온다

<a href="/webtoon/detail.nhn?titleId=662774&no=11&weekday=wed

태그로부터 만화주소를 찾아낸다.

5. 제일마지막화수 알아내기(인덱스에 사용)

최대 화수를 전역변수 max를 사용하여 저장.

max값은 html소스에서 최대화수를 나타내는 값을 불러옴.

이를 이용하여 최대 지정가능한 화수를 정함.

6. 저장한 값을을 배열에 넣기

제일 어려운 부분인 것 같음.

c#에는 배열이 3개있는데

하나는 list

다른하나는 listarray

다른하나는 array

셋의 차이는 잘 모르겠지만 list는 배열의 값을 명시안해주고 막 넣은뒤에 불러올 수 있어서 list를 사용하려했으나 2차원 배열로 list를 다루기가 어려워서 포기

listarray또한 2차원 배열로 다루기가 어려워서 포기

마지막 array로 2차원배열을 사용하기로함. 

헷갈린것은 배열선언할때 0부터 시작하는 것이 아님

ex

[2,3]하면

0ㅁㅁㅁ

1ㅁㅁㅁ임

0ㅁㅁㅁ

1ㅁㅁㅁ

2ㅁㅁㅁ가 아니라

마지막 6

모든 이미지를

쉬운데 진작할걸

[a,b]형식으로 2차원배열을 나타냄.

처음에는 string[,] imgaddr; 전역변수 형식으로 선언한뒤에 후에 max값을 찾아내면 그 때 배열길이를 정함.

총 몇화인지 나타내는 것은 앞의 숫자 뒤에 숫자는 각화의 이미지를 넣으려고함.

각화마다 이미지의 개수가 각각 다르고 이미지가 100개는 안넘어갈테니결국에는 대충 [max,100]으로 지정함

프로그램의 토대는 다만든뒤 추가적인 기능을 구현함.



1.다운로드 경로 지정


2.파일명 사용자가 조절 // 2화 2번째 이미지는 2.2로 저장됨 쓸모없는듯 삭제


3.화수별로 폴더만들어서 넣어주기 체크로 설정


4.다운로드 화 사용자가 조절기능 // 시작값은 0을 넘어야하고, 끝값은 max를 못넘어감


5.만화이름 가져오기 // 위에서 따온것처럼 함.

소스를 가져오면서 getsource사용시 한글이 깨져버리는것을 

Uri url = new Uri(textBox1.Text.

WebClient client = new WebClient();

client.Encoding = System.Text.Encoding.UTF8;

source = client.DownloadString(url);

사용하면 한글로 가져와짐.


기본 저장경로로

string path = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);

뒤의 변수는 유저의 바탕화면 경로.

6. 이미지를 화별로 보여주는 html파일 추가

wrtieline기능으로 구현하기가 쉬웠음.

7.다운받는 화수가 100의 자리가 넘어가면 시간이 많이 걸리기때문에 100의자리가 넘어가면 100단위로 분할하여 다운받는 기능 추가

마지막에 기능 낑겨넣느라 더러워지긴했음. end-start가 100넘어가면 분할한뒤 img다운 함수를 분할한 범위에 각각 사용함.

프로그램을 만드는 도중 이상한것을 깨달았다

이렇게 원시적인 방법이 아니라 더욱 쉽게 가져오는 무언가가 있을터인데...

원초적인 원시적인 파싱말고 무언가 있을것이다...

http://stackoverflow.com/questions/12935398/get-html-element-by-value를 참고한뒤

html태그를 사용하여 데이터 처리하는 방식을 찾아서 사용해보자

일단은 하던방식대로 전부다 하기로함.

약간 막무가내로 만들어서 도중에 혼란스러웠음.

다시한번 깔끔하게 만들어볼 생각

본인은 프로그래밍 공부용으로 만들었음.

모르는 것은 물어보면 대답합니다.


반응형

'C# > C#' 카테고리의 다른 글

C# - Audio Programmning  (1) 2016.04.25
C# 한양대학교 학식 크롤링 프로그램  (0) 2016.03.02
C# 콘솔 Output 보기  (0) 2016.02.24