하나의 서버에서 결과데이타를 두군데의; 매체로 전달(REDIS.QUEUE.NAME을 두가지로)

1. SQLite.Memory.File.Table

C:\Users\xterm\Downloads\ComparisonEstate\EstateStatisticsNodeSearch\RedisTickServer 디렉터리

2025-02-23  오전 09:39       509,194,240 database_all_total.db
2025-02-26  오전 08:46        14,909,440 naver_attach_estate_info_file.db

2. REDIS.ESTATE.Server

3. REDIS.QUEUE.KEY.NAME

QCD:11270016379255255255255 QCK:11270016379255255255255
.NET WPF Program Node.Server.WebBrowser
#if(true)
private void recvWorker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (e.Error != null)
    {
MessageBox.Show("Error: " + e.Error.Message);
    }
    else if (e.Result != null)
    {
if (e.Result is string error)
{
    MessageBox.Show("Error: " + error);
}
else
{
    RealEstateData realEstateData = e.Result as RealEstateData;

    // CapitalGain을 숫자로 변환하여 내림차순 정렬을 위한 준비
    realEstateData.CapitalGain = ConvertWon(realEstateData.CapitalGain);  // 이 부분은 필요에 따라 조정
    realEstateData.TransactionAmount = ConvertWon(realEstateData.TransactionAmount);  // 이 부분은 필요에 따라 조정

    // 실제 데이터를 변환하여 저장
    RealEstateData201 realEstateDisplayData = MapToDisplayData(realEstateData);

    if (realEstateDisplayData != null)
    {
// Add to the list first (this is still useful if needed later)
allRealEstateData201.Add(realEstateDisplayData);

#if(true)
// UI 스레드에서 DataGrid에 추가
Dispatcher.Invoke(() =>
{
    if(realEstateDisplayData.DescendingNumber == "1000")
    {
____realEstateDisplayData = realEstateDisplayData;
    }
    if(realEstateDisplayData.DescendingNumber == "1001")
    {
myDataGrid.Items.Insert(0, realEstateDisplayData);
myDataGrid.Items.Insert(0, ____realEstateDisplayData);
    }
    else
    {
myDataGrid.Items.Insert(0, realEstateDisplayData); // 새 데이터가 항상 첫 번째 행에 추가됨
    }
    BlinkPanel(redPanel, Colors.Gray, Colors.Red);
    myDataGrid.SelectedIndex = 0;
});
#endif
#if(false)
// UI 스레드에서 DataGrid에 하나씩 추가
Dispatcher.Invoke(() =>
{
    // 데이터 추가
    if(realEstateDisplayData.DescendingNumber == "1000")
    {
//myDataGrid.Items.Add(realEstateDisplayData);  // ItemsSource를 전체 다시 설정하지 않고 하나씩 추가
//myDataGrid.Items.Add(realEstateDisplayData);  // ItemsSource를 전체 다시 설정하지 않고 하나씩 추가
____realEstateDisplayData = realEstateDisplayData;
    }
    else if(realEstateDisplayData.DescendingNumber == "1001")
    {
myDataGrid.Items.Add(realEstateDisplayData);  // ItemsSource를 전체 다시 설정하지 않고 하나씩 추가
myDataGrid.Items.Add(____realEstateDisplayData);  // ItemsSource를 전체 다시 설정하지 않고 하나씩 추가
    }
    else
    {
myDataGrid.Items.Add(realEstateDisplayData);  // ItemsSource를 전체 다시 설정하지 않고 하나씩 추가
    }

    // 회색 → 빨간색으로 변경
    BlinkPanel(redPanel, Colors.Gray, Colors.Red);
});
#endif
    }
}
    }

    // Optionally, restart the background worker to continue receiving data
    _recvWorker.RunWorkerAsync();
}
#endif

 

1. Request 는 브라우져에서, Response는 .Net WPF Program 에서
2. Request 는 브라우져에서, Response도 브라우져에서(feat. Node.Js)

 

Query Request)
- Web Browser

Query Response)
- SQLite & Json formatted Data & Send To REDIS



Query Response Data Display)
- Wpf Program


요구사항)
1. 백그라운드 프로세스가 동작하고 있다는 표시(패널사각형 LightGray->DarkBlue)
2. 데이타를 받아서 출력동작을 하고 있다는 표시 (패널사각형 LightGray->DarkRed)

MainWindow.xaml.cs
0.01MB
MainWindow.xaml
0.00MB

 

국토교통부실거래가 + 네이버매매호가를 조합한 통계

지역별 아파트 매매호가대비 실거래가 비율
>Ratio of Actual Transaction Price to Asking Price for Apartment Sales by Region(2019~2024)

현재 네이버매매호가 대비, 과거 실거래가(최대매매가격)을 비교했을때의 비율을 알고싶어서 작성해보았습니다.

 

app.js
0.01MB
index.html
0.02MB

 

부동산.크롤링.국토교통부.실거래가.통계.조회조건추가(금액대별)
부동산.크롤링.국토교통부.실거래가.통계.조회조건추가(금액대별)
부동산.크롤링.국토교통부.실거래가.통계.조회조건추가(금액대별)

조회조건추가)
1. 지역
2. 조회조건
3. 건수
4. 금액대별

 

 

index.html
0.03MB

 

 



1) SQLite 테이블을 메모리기반으로 SQL을 실행할경우

void LoadDatabaseIntoMemory(string filePath, SQLiteConnection memoryConn)
{
    using (var fileConn = new SQLiteConnection($"Data Source={filePath};Version=3;"))
    {
fileConn.Open();
fileConn.BackupDatabase(memoryConn, "main", "main", -1, null, 0);
    }
}
        workingDirectory = Directory.GetCurrentDirectory();

        DESCENDING_DB = Path.Combine(workingDirectory, @"descending_in_base_all.db");
        ANESTATE_DB = Path.Combine(workingDirectory, @"database_all_total.db");
        ESTATENAVER_DB = Path.Combine(workingDirectory, @"naver_attach_estate_info_file.db");

        // 메모리 기반 SQLite 연결 생성
        memoryConn1 = new SQLiteConnection("Data Source=:memory:;Version=3;");
        memoryConn2 = new SQLiteConnection("Data Source=:memory:;Version=3;");
        memoryConn3 = new SQLiteConnection("Data Source=:memory:;Version=3;");

        memoryConn1.Open();
        memoryConn2.Open();
        memoryConn3.Open();

        try
        {
            // 파일 DB 데이터를 메모리 DB로 복사
            LoadDatabaseIntoMemory(DESCENDING_DB, memoryConn1);
            LoadDatabaseIntoMemory(ANESTATE_DB, memoryConn2);
            LoadDatabaseIntoMemory(ESTATENAVER_DB, memoryConn3);

            // 메모리 DB로 사용
            APMSQLite.GetInstance.FetchDescendingConn = memoryConn1;
            APMSQLite.GetInstance.FetchEstateConn = memoryConn2;
            APMSQLite.GetInstance.FetchNaverAttachConn = memoryConn3;

            // 메모리 DB에 테이블이 정상적으로 로드되었는지 확인
            Console.WriteLine("\n===== Memory DB Loaded Tables =====");
            PrintTables(memoryConn1, "Descending DB");
            PrintTables(memoryConn2, "Estate DB");
            PrintTables(memoryConn3, "Naver Attach DB");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"Error: {ex.Message}");
        }

수행시간)

시작: 2025-02-27 10:03:55.089
종료: 2025-02-27 10:04:02.441

  1. 초 차이 계산
    • 10:04:02.441 - 10:03:55.089
    • 02.441초 - 55.089초 = 7.352초
따라서, 두 타임스탬프의 차이는 7.352초입니다.

 

2) SQLite 테이블을 파일기반으로 SQL을 실행할경우

string workingDirectory = Directory.GetCurrentDirectory();

        string DESCENDING_DB = Path.Combine(workingDirectory, @"descending_in_base_all.db");
        string ANESTATE_DB = Path.Combine(workingDirectory, @"database_all_total.db");
        string ESTATENAVER_DB = Path.Combine(workingDirectory, @"naver_attach_estate_info_file.db");
        
        APMSQLite.GetInstance.FetchDescendingConn = new SQLiteConnection($"Data Source={DESCENDING_DB};Version=3;");
        APMSQLite.GetInstance.FetchDescendingConn.Open();
        
        APMSQLite.GetInstance.FetchEstateConn = new SQLiteConnection($"Data Source={ANESTATE_DB};Version=3;");
        APMSQLite.GetInstance.FetchEstateConn.Open();
        
        APMSQLite.GetInstance.FetchNaverAttachConn = new SQLiteConnection($"Data Source={ESTATENAVER_DB};Version=3;");
        APMSQLite.GetInstance.FetchNaverAttachConn.Open();

수행시간

시작: 2025-02-27 10:04:54.994
종료: 2025-02-27 10:05:28.504

  1. 초 차이 계산
    • 10:05:28.504 - 10:04:54.994
    • 분 차이: 10:05 - 10:04 = 1분 (60초)
    • 초 차이: 28.504초 - 54.994초 = -26.490초
    • 1분(60초)을 고려하면, 60 - 26.490 = 33.510초
따라서, 두 타임스탬프의 차이는 33.510초입니다.


결론)
테이블의 데이타를 메모리에 올려서 실행하는것이 파일기반으로 실행하는것보다 5배정도 빠르다.
테이블의 데이타를 메모리에 올려서 실행하는것이 파일기반으로 실행하는것보다 5배정도 빠르다.

 



index.html
0.03MB

국토교통부 실거래가 매매가격 통계조회(조건추가)

조회조건)
1. 매매거래차이 DESC
2. 국토교통부 실거래가 매매가격 DESC
3. (최대매매-최소매매)/(최대매매)*100.0 - 같은아파트,같은평형 DESC
4. (최대매매-최소매매)/(최대매매)*100.0 - 같은아파트,같은평형 ASC

비고)화면이 늦게 나오므로, 인덱스생성

[2025-02-20 12:20:06]>SELECT CityCounty,LotNumber,TransactionAmount,Building,Buyer,Seller,ConstructionYear,RoadName,CancellationReasonDate,TransactionType,BrokerLocation,RegistrationDate FROM ANESTATEAPTALL WHERE MainNumber = '18' AND SubNumber = '10' AND ComplexName = '송도더샵하버뷰(D14)' AND AreaSquareMeters = '101.454' LIMIT 1
[2025-02-20 12:20:06]>SELECT DataClass,InfoMarketClass,TransactionTime,ComplexNo,CortarNo,RealEstateTypeCode,RealEstateTypeName,UseApproveYmd,CortarAddress,MinPriceByLetter,MaxPriceByLetter,MinLeasePriceByLetter,MaxLeasePriceByLetter,MinPrice,MaxPrice,MinLeasePrice,MaxLeasePrice FROM ESTATENAVERALLINFOATTACH WHERE CORTARADDRESS = '인천시 연수구 송도동' AND LNBRMNNM = '18' AND LNBRSLNO = '10' LIMIT 1;
[2025-02-20 12:20:06]>SELECT CityCounty,LotNumber,TransactionAmount,Building,Buyer,Seller,ConstructionYear,RoadName,CancellationReasonDate,TransactionType,BrokerLocation,RegistrationDate FROM ANESTATEAPTALL WHERE MainNumber = '21' AND SubNumber = '59' AND ComplexName = '인천송도힐스테이트3단지' AND AreaSquareMeters = '142.359' LIMIT 1
[2025-02-20 12:20:06]>SELECT DataClass,InfoMarketClass,TransactionTime,ComplexNo,CortarNo,RealEstateTypeCode,RealEstateTypeName,UseApproveYmd,CortarAddress,MinPriceByLetter,MaxPriceByLetter,MinLeasePriceByLetter,MaxLeasePriceByLetter,MinPrice,MaxPrice,MinLeasePrice,MaxLeasePrice FROM ESTATENAVERALLINFOATTACH WHERE CORTARADDRESS = '인천시 연수구 송도동' AND LNBRMNNM = '21' AND LNBRSLNO = '59' LIMIT 1;
Microsoft Windows [Version 10.0.19045.2965]
(c) Microsoft Corporation. All rights reserved.

>sqlite3 "naver_attach_estate_info_file.db"
SQLite version 3.48.0 2025-01-14 11:05:00
Enter ".help" for usage hints.
sqlite> .tables
ESTATENAVERALLINFOATTACH
sqlite> PRAGMA index_list(ESTATENAVERALLINFOATTACH);
sqlite> CREATE INDEX idx_cortar_lnbr ON ESTATENAVERALLINFOATTACH (CORTARADDRESS, LNBRMNNM, LNBRSLNO);
sqlite> PRAGMA index_list(ESTATENAVERALLINFOATTACH);
0|idx_cortar_lnbr|0|c|0
sqlite> PRAGMA index_info(idx_cortar_lnbr);
0|9|CORTARADDRESS
1|18|LNBRMNNM
2|19|LNBRSLNO

>sqlite3 "database_all_total.db"
SQLite version 3.48.0 2025-01-14 11:05:00
Enter ".help" for usage hints.
sqlite> PRAGMA index_list(ANESTATEAPTALL);
sqlite> CREATE INDEX idx_apt_search ON ANESTATEAPTALL (MainNumber, SubNumber, ComplexName, AreaSquareMeters);
sqlite> PRAGMA index_list(ANESTATEAPTALL);
0|idx_apt_search|0|c|0
sqlite> PRAGMA index_info(idx_apt_search);
0|4|MainNumber
1|5|SubNumber
2|6|ComplexName
sqlite> .exit

index.html
0.02MB

카카오 API를 이용해서 지번을 추가입력(지역별 랭킹 매매금액차이)

- 지역별랭킹 매매금액 차이를 구하는건 국토교통부 실거래가자료로 충분한다.
- 위의 아파트정보를 보려면, 결국 네이버부동산과 연결해야 한다.
- 결국 위의 2개의 공통분모를 찾아야하는데, 전체적으로 적용되는것이라, 일일이 찾아서 기록해줄수 없다.
- 자동화해야한다.
- 국토교통부 실거래가자료에는 지번없는주소와 지번이 있다.
- 네이버부동산 크롤링정보에는 지번없는주소와 아파트이름만 있다.
- 카카오API를 통해서 네이버부동산의 지번없는주소와 아파트이름으로 지번을 찾아서 추가해준다.
- 둘의 공통분모가 생겼다.
- 페이지에 표시할수 있고, 해당 아파트 클릭시에 네이버부동산으로 넘어간다.

1. 국토교통부 실거래가 사이트에서 데이타 다운로드 & SQLite 테이블에 지역별로 입력
2. 네이버 전체 APT 크롤링  & SQLite 테이블에 지역별로 입력
3. 네이버 전체 APT 크롤링테이블에서 카카오 API를 이용해서 지번을 추가입력
4. 지역별 랭킹 매매금액차이 SQLite 테이블 생성

빨간부분의 의미는
= (최고매매금액-최소매매금액)/(최고매매금액)*100.0

 

index.html
0.02MB

+ Recent posts