728x90

 

 

AsyncTask는 백그라운드 스레드 와 UI 스레드를 같이 쓰기 쉽게 설계했으며,

 

일반 스레드와 달리, 간단한 작업에 적합하게 만들었다고 설명되어 있다.

 

안드로이드에서의 일처리는 메인스레드(UI 스레드)가 담당한다. 특히 UI와 관련된( ex) TextView,ImageView )

 

일처리는 메인스레드만 담당 하게끔 설계를 했다. 그래서 메인스레드를 UI스레드라고도 불린다.

 

 

따라서 복잡한 계산은 백그라운드 스레드( 메인 스레드가 아닌 다른 스레드의 총칭)에 맡긴후 

 

계산된 결과값을 UI스레드에게 일을 시켜야 하는 것이다.

 

그래서 AysncTask 라는 객체를 만들었고 위에서 설명한 일들을 쉽게 구현 할 수 있도록 메서드를 제공한다.

 

아래의 AysncTask 예시를 보자.



import android.os.AsyncTask;

public class MommooAsyncTask extends AsyncTask<String,Void,String>{

public String result;

@Override
protected void onPreExecute() {
super.onPreExecute();
}

@Override
protected String doInBackground(String... params) {
return result;
}

@Override
protected void onProgressUpdate(Void... values) {
super.onProgressUpdate(values);
}

@Override
protected void onPostExecute(String s) {
super.onPostExecute(s);
}
}

 

AsyncTask 객체는 abstact로 선언되었다 따라서 사용을 위해서는 extends를통해 상속을 받아서 사용하여야 한다

 

@Override
    protected void onPreExecute() {
        super.onPreExecute();
    }



첫번째 메서드다. 해당 메서드는 이름에서 볼 수 있드시,  background스레드를 실행하기전 준비 단계이다.



변수의 초기화나, 네트워크 통신전 셋팅해야할 것들을 위의 메서드 공간에 작성한다. 





 @Override
    protected String doInBackground(String... params) {
        return result;
    }



두번째 메서드다. 해당 메서드가 background 스레드로 일처리를 해주는 곳이다.



보통 네트워크, 병행 일처리등을 위 메서드 공간에 작성한다.



중요한건 마찬가지로 스레드 이므로 UI스레드가 어떤 일을 하고 있는지 상관없이



별개의 일을 진행한다는 점이다. 따라서 AysncTask는 비동기적으로 작동한다.





@Override
    protected void onProgressUpdate(Void... values) {
        super.onProgressUpdate(values);
    }



세번째 메서드는 doInBackground 메서드에서 중간중간에 UI스레드 에게 일처리를 맡겨야 하는 상황일때



쓴다. 매개변수로 Void를 받으므로, doInBackground안에 실제인자가 없이,



 publishProgress( ) 메서드를 호출하면 BackgroundThread 중간에 mainThread에게 일을 시킬 수 있다.





@Override
    protected void onPostExecute(String s) {
        super.onPostExecute(s);
    }



마지막 메서드다. background Thread가 일을 끝마치고 리턴값으로 result를 넘겨준다.



그 값을 지금 보고 있는 해당 메서드가 매개변수로 받은후 받은 데이터를 토데로



UI스레드에 일처리를 시킬때 쓰는 메서드이다.



보통 UI변경 ( ex) textview.setText("~~") )할때 많이 사용된다. 왜냐면



위에서도 말했다시피 UI변경은 메인스레드가 아닌 다른 스레드에서의 변경은 막았기 때문이다.



위에서 만든 AysncTask를 사용 하는방법은 아래와 같이 하면된다.



MommooAsyncTask asyncTask = new MommooAsyncTask();
asyncTask.execute();


출처: https://mommoo.tistory.com/29 [개발자로 홀로 서기]

 

출처 : gangnam-americano.tistory.com/47 

현재 ArrayList를 보면 <>안에 String, List에는 <>안에 int형을 나타내는 Integer가 들어가 있다.



이 <>를 제네릭(Generics)이라 하는데, 이 <>안에 어떠한 타입을 선언해주어 해당 ArrayList, List 등이 사용할 객체의 타입을 지정해준다는 뜻이다. 이는 다룰 객체의 타입을 미리 명시하여 객체의 형변환을 사용할 필요없게 하며, 내가 사용하고 싶은 데이터 타입만 사용할 수 있게 해주는 효과가 있습니다. 

import java.util.ArrayList;
import java.util.List;
 
public class Generics {
 
    public static void main(String[] args) {
        
        ArrayList<String> arrList = new ArrayList<String>();
        
        arrList.add("박지성");
        arrList.add("손흥민");
        arrList.add("기성용");
        
        for(int i=0; i<arrList.size(); i++){
            System.out.println("arrList : " + arrList.get(i));
        }
        
        List<Integer> list = new ArrayList<Integer>();
        list.add(123);
        list.add(456);
        list.add(789);
        
        for(int i=0; i<list.size(); i++){
            System.out.println("list : " + list.get(i));
        }
    }
 
}
Colored by Color Scripter
cs

위의 예시를 보면,



ArrayList는 String으로 선언해주어, ArrayList는 String 객체만 다루게 되며,

List는 Integer로 선언해주어, List는 int형 객체만 다루게 됩니다.

출처: https://gangnam-americano.tistory.com/47

 

 

728x90
728x90

안드로이드 스튜디오를 통해 앱개발을 하고있는 도중

 

웹크롤링을 해야되가지고 jsoup를 통해 웹크롤링을 시도하였는데 되지가 않았다..

 

이걸로 삽질을 몇시간은 한거같은데 저처럼 삽질할분들을위해 정확하게 해결방법을 알려드리겠습니다.

 

 

1. build.gradle(app)에서 dependencies확인

plugins {
    id 'com.android.application'
}

android {
    compileSdkVersion 30
    buildToolsVersion "30.0.2"

    defaultConfig {
        applicationId "com.example.myapplication"
        minSdkVersion 16
        targetSdkVersion 30
        versionCode 1
        versionName "1.0"

        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
    }

    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
    compileOptions {
        sourceCompatibility JavaVersion.VERSION_1_8
        targetCompatibility JavaVersion.VERSION_1_8
    }
}

dependencies {
    implementation 'org.jsoup:jsoup:1.11.3'
    implementation 'androidx.appcompat:appcompat:1.2.0'
    implementation 'com.google.android.material:material:1.2.1'
    implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
    testImplementation 'junit:junit:4.+'
    androidTestImplementation 'androidx.test.ext:junit:1.1.2'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
    implementation 'gun0912.ted:tedpermission:2.0.0'

}

 

2. AndroidMainfest.xml 인터넷사용권한 확인, access, read, write, write_external, read_external 권한 추가

<uses-permission android:name="android.permission.INTERNET"/>


<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />

 

 

AndroidMainfest전체코드 

 

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication">

    <uses-permission android:name="android.permission.INTERNET"/>

    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.READ_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_CONTACTS" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />


    <application
        android:usesCleartextTraffic="true"<!-- 최신안드로이드들의 경우 https통신이 기본이라 http통신을 가능하게 하려면 따로 설정해줘야함 !-->
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.MyApplicationㅁㄴㅇㅇㅁㄴ">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

 

1번과2번을 잘 해결햇다면

 

jsoup 크롤링코드를 메인activity에서 잘짜면된다

주의할점은

백그라운드에서 실행되어야 된다는점

이거때문에 몇시간동안 삽질한거같다...

 

AsyncTask를 이용하여 백그라운드 처리를 해주면된다.

다른방법으로는 php에서 파싱처리한 결과를 안드로이드에서 JSON으로 가져오는 방법도있다고하지만

여기까지는 저도 아직 부족한거같아서 백그라운처리를통해 크롤링을 배웠습니다.

 

 

MainAcitivity.java

package com.example.myapplication;

import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;

import android.content.Context;
import android.content.DialogInterface;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.AsyncTask;
import android.os.Build;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

import com.gun0912.tedpermission.PermissionListener;
import com.gun0912.tedpermission.TedPermission;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

import java.io.IOException;
import java.util.ArrayList;

public class MainActivity extends AppCompatActivity {


    Context context;
    TextView textView1, textView2;
    String text1,text2,text3;
    PermissionListener permissionlistener = new PermissionListener() {
        @Override
        public void onPermissionGranted() {
            initView();
        }

        @Override
        public void onPermissionDenied(ArrayList<String> deniedPermissions) {
            Toast.makeText(MainActivity.this, "권한 허용을 하지 않으면 서비스를 이용할 수 없습니다.", Toast.LENGTH_SHORT).show();
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        context = MainActivity.this;

        // 네트워크 연결상태 체크
        if (NetworkConnection() == false)
            NotConnected_showAlert();
        checkPermissions();
    }

    private void checkPermissions() {
        if (Build.VERSION.SDK_INT >= 23) { // 마시멜로(안드로이드 6.0) 이상 권한 체크
            TedPermission.with(context)
                    .setPermissionListener(permissionlistener)
                    .setRationaleMessage("앱을 이용하기 위해서는 접근 권한이 필요합니다")
                    .setDeniedMessage("앱에서 요구하는 권한설정이 필요합니다...\n [설정] > [권한] 에서 사용으로 활성화해주세요.")
                    .setPermissions(new String[]{
                            android.Manifest.permission.WRITE_CONTACTS, // 주소록 액세스 권한
                            android.Manifest.permission.READ_EXTERNAL_STORAGE,
                            android.Manifest.permission.WRITE_EXTERNAL_STORAGE // 기기, 사진, 미디어, 파일 엑세스 권한
                    }).check();

        } else {
            initView();
        }
    }

    private void initView() {
        textView1 = findViewById(R.id.weather_rs1);
        textView2 = findViewById(R.id.weather_rs2);

        String path1 = "https://weather.naver.com/today/02273610"; //안산 단원구
        String path2 = "https://weather.naver.com/rgn/cityWetrCity.nhn?cityRgnCd=CT008008";
        new getData1().execute(path1);
        new getData2().execute(path2);
    }

    private class getData1 extends AsyncTask<String, Void, String> {
        // String 으로 값을 전달받은 값을 처리하고, Boolean 으로 doInBackground 결과를 넘겨준다.
        @Override
        protected String doInBackground(String... params) {
            try {
                Document document = Jsoup.connect(params[0].toString()).get();
                Elements elements = document.select(".weather"); // 내용중에서 원하는 부분을 가져온다.
                String[] str = elements.text().split(" ");

                Document document1 = Jsoup.connect(params[0].toString()).get();
                Elements elements1 = document.select(".current"); // 내용중에서 원하는 부분을 가져온다.
                String[] str1 = elements1.text().split(" ");

                Document document2 = Jsoup.connect(params[0].toString()).get();
                Elements elements2 = document.select(".value"); // 내용중에서 원하는 부분을 가져온다.
                String[] str2 = elements2.text().split(" ");


                String text = "\n날씨 : "+str[0] + "\n온도 : " + str1[1] + "\n미세먼지 : " + str2[0];

                return text;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            textView1.setText("<안산>  "+result);
        }
    }

    private class getData2 extends AsyncTask<String, Void, String> {
        // String 으로 값을 전달받은 값을 처리하고, Boolean 으로 doInBackground 결과를 넘겨준다.
        @Override
        protected String doInBackground(String... params) {
            try {
                Document document = Jsoup.connect(params[0].toString()).get();
                Elements elements = document.select("em");
                Element targetElement1 = elements.get(1);//1.현시간 2.온도 3.미세먼지
                Element targetElement2 = elements.get(2);//1.현시간 2.온도 3.미세먼지
                Element targetElement3 = elements.get(3);//1.현시간 2.온도 3.미세먼지
                String text1 = targetElement1.text();
                String text2 = targetElement2.text();
                String text3 = targetElement3.text();
                String text = "시간 : "+text1 + " ,날씨 : " + text2 + " ,미세먼지 : " + text3;

                return text;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            //textView2.setText("\n\n\n부산 : "+result);
        }
    }

    private void NotConnected_showAlert() {

        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("네트워크 연결 오류");
        builder.setMessage("사용 가능한 무선네트워크가 없습니다.\n" + "먼저 무선네트워크 연결상태를 확인해 주세요.")
                .setCancelable(false)
                .setPositiveButton("확인", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        finish(); // exit
                        //application 프로세스를 강제 종료
                        android.os.Process.killProcess(android.os.Process.myPid());
                    }
                });
        AlertDialog alert = builder.create();
        alert.show();

    }

    private boolean NetworkConnection() {
        int[] networkTypes = {ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_WIFI};
        try {
            ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            for (int networkType : networkTypes) {
                NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
                if (activeNetwork != null && activeNetwork.getType() == networkType) {
                    return true;
                }
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }
}



실행결과

안드로이드스튜디오 

백그라운드 관련 글 

itmining.tistory.com/5

itmining.tistory.com/6

itmining.tistory.com/7

<코드설명>

Context context; // perrmission을 체크하기 위해 선언
PermissionListener permissionlistener = new PermissionListener() {
        @Override
        public void onPermissionGranted() {
            initView();
        }

        @Override
        public void onPermissionDenied(ArrayList<String> deniedPermissions) {
            Toast.makeText(MainActivity.this, "권한 허용을 하지 않으면 서비스를 이용할 수 없습니다.", Toast.LENGTH_SHORT).show();
        }
    };

PermissioinListener 체크하기 위해  객체를 만들었으며

Override함수재정의를 통해 권한이 모두 허가되어있지않을경우 토스트를 띄우며

권한이 허용되어있을경우 initView()함수를 실행한다. 

 

private void initView() {
        textView1 = findViewById(R.id.weather_rs1);
        textView2 = findViewById(R.id.weather_rs2);

        String path1 = "https://weather.naver.com/today/02273610"; //안산 단원구
        String path2 = "https://weather.naver.com/rgn/cityWetrCity.nhn?cityRgnCd=CT008008";
        new getData1().execute(path1);
        new getData2().execute(path2);
    }

initView함수의 경우 textView를 Mainactivity의 텍스트뷰를 각각 연결시켜주고

path에(path2는 실질적으로 사용x)에 안산의 네이버날씨 주소를 저장해놓고

getData()함수와 execute함수를 통해 데이터를 알맞게 크롤링한후 setText해준다.

 

public final boolean execute(
    java.lang.String sql,
    int[] columnIndexes)
    
    매개 변수
SQL 문이 포함된 문자열입니다.
자동 생성 키의 열 인덱스를 사용할 수 있도록 해야 하는지 여부를 나타내는 int의 배열입니다.


반환 값
첫 번째 결과가 결과 집합이면 true이고, 그렇지 않으면 false입니다.

 

private class getData1 extends AsyncTask<String, Void, String> {
        // String 으로 값을 전달받은 값을 처리하고, Boolean 으로 doInBackground 결과를 넘겨준다.
        @Override
        protected String doInBackground(String... params) {
            try {
                Document document = Jsoup.connect(params[0].toString()).get();
                Elements elements = document.select(".weather"); // 내용중에서 원하는 부분을 가져온다.
                String[] str = elements.text().split(" ");

                Document document1 = Jsoup.connect(params[0].toString()).get();
                Elements elements1 = document.select(".current"); // 내용중에서 원하는 부분을 가져온다.
                String[] str1 = elements1.text().split(" ");

                Document document2 = Jsoup.connect(params[0].toString()).get();
                Elements elements2 = document.select(".value"); // 내용중에서 원하는 부분을 가져온다.
                String[] str2 = elements2.text().split(" ");


                String text = "\n날씨 : "+str[0] + "\n온도 : " + str1[1] + "\n미세먼지 : " + str2[0];

                return text;
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(String result) {
            textView1.setText("<안산>  "+result);
        }
    }

 

백그라운드 실행을위해 public class extends AsyncTash<String, void, String> { } 선언을 하였고

 

백그라운드에서 실행되는함수 doIngBackground()함수를 통해 크롤링을 진행해준다.

 

그리고 결과값을 반환해주는(setText 해주는) onPostExecute()함수

 

 

private void NotConnected_showAlert() {

        AlertDialog.Builder builder = new AlertDialog.Builder(MainActivity.this);
        builder.setTitle("네트워크 연결 오류");
        builder.setMessage("사용 가능한 무선네트워크가 없습니다.\n" + "먼저 무선네트워크 연결상태를 확인해 주세요.")
                .setCancelable(false)
                .setPositiveButton("확인", new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int id) {
                        finish(); // exit
                        //application 프로세스를 강제 종료
                        android.os.Process.killProcess(android.os.Process.myPid());
                    }
                });
        AlertDialog alert = builder.create();
        alert.show();

    }

 

 

 

 

NotConnected_showAlert()함수는 네트워크 연결여부를 체크하는게아니라 

 

if()문을통해 인터넷에 연결되어있지않을경우 

 

"네트워크가 연결이 되어있지않았다고" 해당 문자열을 출력하고 죵료하는 함수

 

private boolean NetworkConnection() {
        int[] networkTypes = {ConnectivityManager.TYPE_MOBILE, ConnectivityManager.TYPE_WIFI};
        try {
            ConnectivityManager manager = (ConnectivityManager) getSystemService(Context.CONNECTIVITY_SERVICE);
            for (int networkType : networkTypes) {
                NetworkInfo activeNetwork = manager.getActiveNetworkInfo();
                if (activeNetwork != null && activeNetwork.getType() == networkType) {
                    return true;
                }
            }
        } catch (Exception e) {
            return false;
        }
        return false;
    }

NetworkConnection()함수는 네트워크 연결여부를 체크하는 함수로

네트워크가 연결되어있을경우 true값을

네트워크에 연결되어있지않을경우 false값을 반환한다.

 

 

private void checkPermissions() {
        if (Build.VERSION.SDK_INT >= 23) { // 마시멜로(안드로이드 6.0) 이상 권한 체크
            TedPermission.with(context)
                    .setPermissionListener(permissionlistener)
                    .setRationaleMessage("앱을 이용하기 위해서는 접근 권한이 필요합니다")
                    .setDeniedMessage("앱에서 요구하는 권한설정이 필요합니다...\n [설정] > [권한] 에서 사용으로 활성화해주세요.")
                    .setPermissions(new String[]{
                            android.Manifest.permission.WRITE_CONTACTS, // 주소록 액세스 권한
                            android.Manifest.permission.READ_EXTERNAL_STORAGE,
                            android.Manifest.permission.WRITE_EXTERNAL_STORAGE // 기기, 사진, 미디어, 파일 엑세스 권한
                    }).check();

        } else {
            initView();
        }
    }

Build.VERSION.SDK_INT >= 23 안드로이드(6.0)이 Build.VERSION.SDK_INT 23 인가보다...? 쩃든 6.0 이상일경우 

 

TedPermission.with(context)
.setPermissionListener(permissionlistener)
.setRationaleMessage("앱을 이용하기 위해서는 접근 권한이 필요합니다")
.setDeniedMessage("앱에서 요구하는 권한설정이 필요합니다...\n [설정] > [권한] 에서 사용으로 활성화해주세요.")
.setPermissions(new String[]{
android.Manifest.permission.WRITE_CONTACTS, // 주소록 액세스 권한
android.Manifest.permission.READ_EXTERNAL_STORAGE,
android.Manifest.permission.WRITE_EXTERNAL_STORAGE // 기기, 사진, 미디어, 파일 엑세스 권한
}).check();

 

이 긴 문법을통해 접근권한이 필요하다고 띄운후 각각의 권한들을 요구하고 체크한다

만약 false(하나라도 권한이 허용되어있지않을경우 종료됨)

728x90
728x90

 

하루하루 미치게 올라가고있는 코스피 지수를 파이썬을 통해 실시간으로 크롤링하는 방법을 알아보겠습니다.

 

finance.naver.com/

 

네이버 금융

국내 해외 증시 지수, 시장지표, 펀드, 뉴스, 증권사 리서치 등 제공

finance.naver.com

네이버 금융을 실시간으로 크롤링하여 코스피지수를 긁어와보겠습니다.

 

네이버 금융에 들어가서

크롬 f12를 눌러 보면

 

코스피지수의 span.num 해당클래스이름과 태그등이 나옵니다.

 

이제 이것을가지고 실시간으로 크롤링하면됩니다.

 

import urllib.request
from bs4 import BeautifulSoup
import json
from urllib import parse
from collections import OrderedDict
from datetime import datetime

 

basic_url = "https://finance.naver.com/sise/"

fp = urllib.request.urlopen(basic_url)

source = fp.read()

fp.close()

soup = BeautifulSoup(source, 'html.parser')
soup = soup.findAll("span",class_="num")


kospi_value = soup[0].string
kosdaq_value = soup[1].string
#print(soup)

print(kospi_value)
print(kosdaq_value)

이렇게하면 코스피지수와 코스닥지수가 출력되는것이 보입니다.

2,542.85

845.39 이렇게 짧게 실시간으로 코스피 , 코스닥지수를 크롤링하여 긁어올수있습니다.

 

+) 

json형식으로 만들기

 

#json 형식으로 만들기 여기코드는 안쓰셔도 됩니다...

stock_data = OrderedDict()

stock_data['kospi'] = kospi_value



print(stock_data)
print(type(stock_data))

 

 

728x90
728x90

주식관련 프로그램(앱)을 개발하는 도중 실시간으로 주식데이터를 어떻게 가져올까 고민하던도중

파싱을 통해 데이터를 가져오고자 해결방법이 떠올랐다.

 

간단하게 전체과정을 설명하자면

 

pandas를 통해 전체상장된 주식들에 대한 종목명:종목코드를 

엑셀로 알맞게 저장한다음 

이름을 검색하면 그에 대한 종목코드를 반환하여

 

finance.naver.com/item/sise_day.nhn?code=!!!종목코드!!!

로 들어가 해당 주식에대한 날짜 종가 시가 고가 거래량 등등을 저장한다

 

 

1. pandas라이브러리 설치하기

 

python -m pip install --upgrade pip  ( pip 는 항상 먼저 업그레이드하는 습관.,...)

 

pip install pandas ( 판다르 라이브러리 설치)

 

 

http://kind.krx.co.kr/corpgeneral/corpList.do?method=download&searchType=13

위에 링크는 한국증권거래소에서 제공하는 상장법인목록 엑셀파일이다.

 

 

 

import pandas as pd 

#모든 상장된 주식에 대한 종목명,종목코드 등등 여러정보를 담고있는 엑셀파일
stock_code = pd.read_html('http://kind.krx.co.kr/corpgeneral/corpList.do?method=download', header=0)[0] 
#우리에게 필요한정보는 회사명:종목코드 이므로 나머지 데이터들은 제거
stock_code = stock_code[['회사명', '종목코드']] 
#종목코드는 6자리이므로 6자리로 format
stock_code.code = stock_code.code.map('{:06d}'.format) 

 

company='LG화학'
#LG화학의 종목코드를 code에 담는다.
code = stock_code[stock_code.company==company].code.values[0].strip() ## strip() : 공백제거
#크롤링할때 page=1,2,3,4,5....인데 한페이지의 데이터만 크롤링할거라 page는 1로 저장
page = 1

 

#이부분은 직접 code부분에 상장코드를 들어가보면 이해가 될것이다. code부분을 code로 foramt
url = 'http://finance.naver.com/item/sise_day.nhn?code={code}'.format(code=code)
#url 에 page추가 1페이지당 약4~5일? 의 데이터들이 담겨있음
url = '{url}&page={page}'.format(url=url, page=page)
print(url)
#html을 불러옴
df = pd.read_html(url, header=0)[0]
#출력
df.head()

 

df = pd.DataFrame()
for page in range(1,21):
    url = 'http://finance.naver.com/item/sise_day.nhn?code={code}'.format(code=code)     
    url = '{url}&page={page}'.format(url=url, page=page)
    print(url)
    df = df.append(pd.read_html(url, header=0)[0], ignore_index=True)
    
    
#공휴일, 거래정지등 NaN값이 있을것같아서 결측값이 있는 행을 제거함
df = df.dropna()
#df에 담긴 10개의 데이터 출력
df.head(10)
#df.to_excel('lg화학df.xlsx')

 

LG화학의 주가데이터파일이 잘출력된다. 

 

df.to_excel('lg화학df.xlsx') 코드를 마지막에 추가하면 df을 엑셀파일로 저정할수있다. (pandas 데이터프레임을 엑셀로 저장하기)

 

엑셀파일로 성공적으로 저장했으며

 

데이터프레임도 잘 저장되어있다.

for반복문에 범위만 바꾸면 2020-01-29이전의 데이터들도 모두 저장할수있다.

728x90
728x90

 

 

 

목적 : 각레이아웃을 구분하는 표시선을 그으려고하는데 방법은?

 

노가다 방법으로 가장 많이?? 쓰이는거같은데

 

각 레이아웃에 View를 추가하여 weigth , height를 각각 martch나 1dp로 설정하여

background에 검정색을 추가해준다. (예제코드는 흰색으로 해놨음)

 

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.project03.MainActivity"
    >

    <LinearLayout

        android:layout_width="match_parent"
        android:layout_height="50dp"
        android:gravity="center"
        android:orientation="horizontal"
        >


        <Button
            android:id="@+id/bt1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="화면1" />

        <Button
            android:id="@+id/bt2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="화면2" />

        <Button
            android:id="@+id/bt3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="화면3" />

    </LinearLayout>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="200dp"
        android:weightSum="2"
        >


            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                >
                <View
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:layout_centerInParent="true"
                    android:background="#ffffff"
                    tools:layout_editor_absoluteX="-16dp"
                    tools:layout_editor_absoluteY="192dp" />
                <ImageView
                    android:id="@+id/image_view1"
                    android:layout_width="match_parent"
                    android:layout_height="match_parent"
                    android:adjustViewBounds="true">
                </ImageView>




            </LinearLayout>

            <LinearLayout
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:layout_weight="1"
                >

                <View
                    android:layout_width="1dp"
                    android:layout_height="match_parent"
                    android:layout_centerInParent="true"
                    android:background="#ffffff"
                    tools:layout_editor_absoluteX="-16dp"
                    tools:layout_editor_absoluteY="192dp" />
                <View
                    android:layout_width="match_parent"
                    android:layout_height="1dp"
                    android:layout_centerInParent="true"
                    android:background="#ffffff"
                    tools:layout_editor_absoluteX="-16dp"
                    tools:layout_editor_absoluteY="192dp" />



            </LinearLayout>




    </LinearLayout>



    <FrameLayout
        android:id="@+id/main_frame"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        >

        <View
            android:layout_width="match_parent"
            android:layout_height="1dp"
            android:layout_centerInParent="true"
            android:background="#ffffff"
            tools:layout_editor_absoluteX="-16dp"
            tools:layout_editor_absoluteY="192dp" />
    </FrameLayout>


</LinearLayout>

 

실행결과:

 

728x90
728x90

안드로이드 앱개발을위해 안드로이드 스튜디오를 설치하기 전

 

오라클 홈페이지에서 JDK8 버전 이상을 설치받아야 한다. ( 자신의 운영체제에 맞게 설치합시다)

 

www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-2133151.html

전부 NEXT만 눌러주셔서 설치하시면 됩니다. 

 

+) 예전에는 JDK 설치과정에서 로그인이 필요없었는데

 

최근에 설치하니까 오라클 로그인이 필요한거같습니다... 오라클 계정이 없으신분들은 

 

오라클 회원가입을하여 JDK를 설치받도록합시다.

 

 

 

JDK가 설치가 완료되었다면

 

이제 안드로이드 스튜디오를 설치합니다..

 

developer.android.com/studio/

 

Download Android Studio and SDK tools  |  Android 스튜디오

developer.android.com

 

 

 

다운로드를 하여 설치하시면서

 

따로 건드리는거없이 NEXT만 눌러줍니다.

 

그러면 쉽게 설치가 완료됩니다.

 

728x90
728x90

styles.xml에

 

<item name='windowNoTitle">true</item> 한줄을 추가해주면 모든 액티비티에서 상태바가 사라진다.

 

만약 전체 액티비티가 아니라 자신이 원하는 액티비티에서만 상태바를 제거하고싶다면

onCreate()에서 setContentView(R.layout.activity_main) 코드를 추가해주면된다.

그러면 해당 엑티비티에서 상태바가 사라진다.

 

728x90

+ Recent posts