【Python】スクレイピングしてみた

日経トップページから、トップニュース15件?を抜き出してみた。
http://www.nikkei.com/

日本経済新聞様、マズければご指摘ください)

以下ソース。

import urllib.request
from bs4 import BeautifulSoup
import pprint

url = "http://www.nikkei.com/"
response = urllib.request.urlopen(url)
data = response.read()

soup = BeautifulSoup(data,"html.parser")

article = []

#トップニュース取得
top = soup.find(class_ = "nx-top_news_first cmn-clearfix")
top = top.find(class_="cmnc-large")
article.append(top.string)

#セカンドニュース?取得
seconds_all = soup.find(class_="nx-top_news_second cmn-clearfix")
seconds = seconds_all.find_all(class_="cmnc-middle")
#print(seconds)
for i in range(len(seconds)):
    art = seconds[i].string
    article.append(art)
    #print(art)

#forth news取得
fourth_all = soup.find_all(class_="nx-top_news_fourth cmn-clearfix")
for i in range(len(fourth_all)):
    art = fourth_all[i].find(class_="cmnc-xsmall")
    article.append(art.string)
    #print(art.string)

#print(article)
#print(len(article))

#\u3000を置換、表示
result = []
for i in range(len(article)):
    s = str(article[i])
    s = s.replace('\u3000',' ')
    print(s)
    result.append(s)

#print(result)
print(len(result))

実行結果は以下の通り。
f:id:ossannt:20170728161916p:plain

(python) 位相アンラップしてみた

ちょっと便利すぎやしないかい?python
10年くらい前にC++で書いたオレオレ信号処理ライブラリが完全に陳腐化したわ。

sin関数の位相にガウス関数を加えたもの。
{\displaystyle sin(2\pi ft + 10\exp(- \frac{ (x-5)^{ 2 }}{2} ) ) }

これから
{\displaystyle 10\exp(- \frac{ (x-5)^{ 2 }}{2})}
を抽出するのが目標。

f:id:ossannt:20170724143801p:plain

FFTして負の周波数成分をカット=ヒルベルト変換
f:id:ossannt:20170724150440p:plain

IFFTして、元の関数の虚数部を復元(解析信号の取得)
f:id:ossannt:20170724150516p:plain

解析信号の位相。±πにラップされている。
f:id:ossannt:20170724150557p:plain

アンラップした位相。ほぼ傾き{\displaystyle 2\pi ft}の直線だが、
少しもっこりしている。
f:id:ossannt:20170724150630p:plain

傾き{\displaystyle 2\pi ft}を引く。
ピークがx=5のガウス関数が得られている。
f:id:ossannt:20170724150815p:plain

以下ソース。

import numpy as np
from scipy.fftpack import fft
from scipy.fftpack import ifft
from scipy.fftpack import fftfreq
from scipy.fftpack import fftshift
import matplotlib.pyplot as plt
import pandas as pd
import math

#データ数
N = 1000

#サンプリング周期(sec)
dt = 0.01

#周波数  
f = 1.0

#時間軸       
t = np.linspace(1,N,N) * dt - dt

#時系列データ
#y = np.sin(2 * np.pi * f * t)

#f(x)を自分で定義
#ガウス関数
fx = lambda x: (math.exp(-(x-5)**2/2)) /  math.sqrt(2*math.pi) * 10

y = []
for i in range(len(t)):
    y.append(np.sin(2 * np.pi * f * t[i] + fx(t[i])))
    #y.append(fx(t[i]))

#周波数軸(MATLAB等で言うfftshiftがかかっている)
freq = fftfreq(N,dt)

#FFT
yf = fft(y)

#解析信号を得る
yf[int(N/2):N] = 0.0 + 0.0j
af = ifft(yf)

#unwrap
unwrap = np.unwrap(np.angle(af))

phase = []
for i in range(len(t)):
    phase.append(unwrap[i] - 2*np.pi * f * t[i]) #オフセットを引く

plt.figure(1)
plt.xlabel("time(sec)")
plt.ylabel("value(a.u.)")
plt.plot(t,y)

plt.figure(2)
plt.xlabel("freq(Hz)")
plt.ylabel("amplitude(a.u.)")
plt.plot(freq,np.abs(yf))

plt.figure(3)
plt.xlabel("time(sec)")
plt.ylabel("value(a.u.)")
plt.plot(t,np.real(af))
plt.plot(t,np.imag(af))

plt.figure(4)
plt.xlabel("time(sec)")
plt.ylabel("phase(rad)")
plt.plot(t,np.angle(af))

plt.figure(5)
plt.xlabel("time(sec)")
plt.ylabel("phase(rad)")
plt.plot(t,unwrap)

plt.figure(6)
plt.xlabel("time(sec)")
plt.ylabel("phase(rad)")
plt.plot(t,phase)

plt.show()

python(scipy?)にunwrap関数なんてあるのね。
今回はFFTして負の周波数成分をカットして・・・という方法で実装しているけど、
hilbert関数というのがあるので、そちらを使った方が早いかも知れない。
やってることは同じはずだけども。

pythonでFFTしてみた

便利な世の中になったもんだ。
参考にしたのは
org-technology.com
ism1000ch.hatenablog.com
など。
ソースは以下。

import numpy as np
from scipy.fftpack import fft
from scipy.fftpack import fftfreq
from scipy.fftpack import fftshift
import matplotlib.pyplot as plt
import pandas as pd

#データ数
N = 800   

#サンプリング周期(sec)
dt = 0.001

#周波数  
f = 5.0

#時間軸       
t = np.linspace(1,N,N) * dt - dt

#時系列データ
y = np.sin(2 * np.pi * f * t)

#周波数軸(MATLAB等で言うfftshiftがかかっている)
freq = fftfreq(N,dt)

#FFT
yf = fft(y)

plt.figure(1)
plt.xlabel("time(sec)")
plt.ylabel("value(a.u.)")
plt.plot(t,y)

plt.figure(2)
plt.xlabel("freq(Hz)")
plt.ylabel("amplitude(a.u.)")
plt.plot(freq,np.abs(yf))
#plt.plot(freq,np.real(yf)) #実部
#plt.plot(freq,np.imag(yf)) #虚部

print(np.real(yf))
plt.show()

df = pd.DataFrame(freq)
df.to_csv("freq.csv")


5Hzのsin波
f:id:ossannt:20170720231304p:plain

FFT結果(power)
f:id:ossannt:20170720231307p:plain

(C#)絶対に二重起動させない方法

毎回忘れるのでメモ。
この方法だと、絶対に二重起動しない。
Application.Run()がusingの中に入っているのがミソ。

[STAThread]
    static void Main() {
        using (Mutex mutex = new Mutex(false, "APP NAME")) {
            if (mutex.WaitOne(0, false) == false) {
                MessageBox.Show("二重起動はできません。", "APP NAME");
                return;
            }
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new MainForm());
        }
            
    }

(BLE)WindowsでKonashiのアナログ入力を読む

ようやくできたよ・・・。
Windows 10のノートPCで動作確認。他は知らない。
ハマったポイントは、
characteristic.ReadValueAsync()メソッドが、デフォルトでキャッシュした値を返していたこと。
BluetoothCacheMode enumeration - Windows app development
にあるように、引数をunchachedにしたら、ちゃんと読めた。

以下ソース。

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Runtime.InteropServices.WindowsRuntime;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.Devices.Bluetooth;
using Windows.Devices.Bluetooth.GenericAttributeProfile;
using Windows.Devices.Enumeration;
using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Popups;


namespace BreathMonitorKonashi {

    public sealed partial class MainPage : Page {

        private const string KONASHI_SERVICE = "229BFF00-03FB-40DA-98A7-B0DEF65C2D4B";
        private const string KONASHI_AIO0_CHARACTERISTIC = "229B3008-03FB-40DA-98A7-B0DEF65C2D4B";

        private GattDeviceService service;
        private GattCharacteristic characteristic;

        Timer timer;


        public MainPage() {
            this.InitializeComponent();
        }

        private async void btnConnect_Click(object sender, RoutedEventArgs e) {
            //デバイスを検索
            var selector = GattDeviceService.GetDeviceSelectorFromUuid(new Guid(KONASHI_SERVICE));
            var deviceInfomations = await DeviceInformation.FindAllAsync(selector);
            var deviceInfomation = deviceInfomations.FirstOrDefault();
            if (deviceInfomation != null) {
                //サービス取得
                this.service = await GattDeviceService.FromIdAsync(deviceInfomation.Id);

                //キャラクタリスティック取得
                var characteristics = this.service.GetCharacteristics(new Guid(KONASHI_AIO0_CHARACTERISTIC));
                if (characteristics.Count > 0) {
                    this.characteristic = characteristics.First();
                    
                    var dialog = new MessageDialog("Connected to " + deviceInfomation.Name);
                    await dialog.ShowAsync();

                    //ADC読み取りスレッド開始
                    TimerCallback timerDelegate = new TimerCallback(onTimer);
                    timer = new Timer(timerDelegate, null, 0, 100);
                }
            }
        }


        private async void onTimer(object sender) {
            if (characteristic == null) {
                return ;
            }
            
            var result = await characteristic.ReadValueAsync(BluetoothCacheMode.Uncached);  //キャッシュしてやがった!
            byte[] value = result.Value.ToArray();
            
            int val = (value[0] << 8) + value[1];   //[0]番目に上位バイト、[1]番目に下位バイト
            System.Diagnostics.Debug.WriteLine(val);

            lastVal = val;
            
        }


    }
}

(UWP)プロジェクト作成でコケるときのおまじない

いろいろ調べたけど、おまじないで逃げることにする。

プロジェクト作成したら、パッケージマネージャで、

PM> Install-Package Microsoft.NETCore.UniversalWindowsPlatform

を実行。

(Java,Android)twitter4jで最新のユーザータイムライン1つだけ取得する

題記の通り。
これで、5秒に1回の頻度(?)で監視できる。

Paging paging = new Paging();
paging.setCount(1); //1個に指定
List<twitter4j.Status> statuses =twitter.getUserTimeline("ユーザ名", paging);
final Status status = statuses.get(0);
Log.d("twitter4j", status.getUser().getScreenName() + " - " + status.getText());