コミケ73のヤフオクデータ収集中

今回は調子を見るために早めに12/25あたりから動かし始めている。


このプログラムは初めて年を越すため早速バグ発見。ヤフオクのページ上日付が月日単位しか表示されないので、年データを補完しなければならないということがわかった。


あと1回の巡回に1時間くらいかかっているのでどうしても即決分で取りこぼしが避けられない。
もうちょっと精度を上げるためにもうちょっと巡回間隔を短くしたいが、Excel VBAで作っている以上シングルタスクでしか動作できない。
今日はちょっとひらめいたのでプログラムに手を入れて擬似マルチスレッドにしてみた。

    Do
        For n = 0 To 1
            Select Case current_phase(n)
            
                Case PHASE_INIT
                    origin_url(n) = objIEs(n).locationurl
                    ready_retry(n) = 0
                    current_phase(n) = PHASE_NAVIGATE
                    
                Case PHASE_NAVIGATE
                    navigate_retry(n) = 0
                    If origin_url(n) = target_url(n) Then
                        objIEs(n).Refresh
                        current_phase(n) = PHASE_NAVIGATED
                    Else
                        objIEs(n).navigate target_url(n)
                        time_out(n) = 1 / 24 / 60 / 60
                        stt(n) = Now()
                        next_phase(n) = PHASE_CONFIRMNAVIGATED
                        current_phase(n) = PHASE_WAITTIME
                    End If
                    
                Case PHASE_CONFIRMNAVIGATED
                    stt(n) = Now()
                    current_phase(n) = PHASE_CONFIRMNAVIGATED2
                
                Case PHASE_CONFIRMNAVIGATED2
                    If Now() - stt(n) > 1 / 24 / 20 Then
                        ' navigate retry
                        navigate_retry(n) = navigate_retry(n) + 1
                        If navigate_retry(n) < 3 Then
                            current_phase(n) = PHASE_NAVIGATE
                        Else
                            AsyncGetUrlByIE = RESULT_FAILURE Or n
                            current_phase(n) = 0
                            Exit Function
                        End If
                    Else
                        If objIEs(n).locationurl <> origin_url(n) _
                            And objIEs(n).locationurl = target_url(n) _
                        Then
                            current_phase(n) = PHASE_NAVIGATED
                        End If
                    End If
                    
                Case PHASE_NAVIGATED
                    If Not objIEs(n).busy Then
                        current_phase(n) = PHASE_NAVIGATE_DONE
                    End If
                    
                Case PHASE_NAVIGATE_DONE
                    stt(n) = Now()
                    current_phase(n) = PHASE_WAIT_READY
                    
                Case PHASE_WAIT_READY
                    If Now() - stt(n) > 1 / 24 / 60 Then
                        ' navigate retry
                        ready_retry(n) = ready_retry(n) + 1
                        If ready_retry(n) < 3 Then
                            current_phase(n) = PHASE_NAVIGATE
                        Else
                            AsyncGetUrlByIE = RESULT_FAILURE Or n
                            current_phase(n) = 0
                            Exit Function
                        End If
                    Else
                        If objIEs(n).readystate >= 2 Then
                            current_phase(n) = PHASE_READY
                        End If
                    End If
                
                Case PHASE_READY
                    current_phase(n) = 0
                    Exit Do
                
                Case PHASE_WAITTIME
                    If Now() - stt(n) > time_out(n) Then
                        current_phase(n) = next_phase(n)
                        next_phase(n) = 0
                    End If
                    
                Case Else
                    current_phase(n) = PHASE_INIT
            
            End Select
        Next n
        DoEvents
    Loop


IEオブジェクトを複数作成して、それぞれnavigateさせれば、各IEオブジェクトはExcel VBAのメインスレッドとは別スレッドで動作するため、少なくともHTMLデータ取得にかかるコストだけはマルチスレッド化することが可能。但し、シリアルなフローにできないのでこんな感じでステートマシンで管理してかないといけないので結構面倒くさい。割り込みをポーリングで管理しなければならないOSにでもなった気分だ。


ただ、HTML取得後のHTMLの解析処理はVBA部分なのでここはシーケンシャルになってしまう。しかし、解析処理を行っている間にもIEオブジェクト側は非同期でページの読み込みを続けられるので、全体の巡回時間はかなり削減できた。
理論上は2スレッド以上でもいけるが、どうやってURLをフィードするかが課題。第1段階としては一般カテゴリとアダルトカテゴリで2スレッド動作がもっとも単純。第2段階はそれぞれ奇数ページと偶数ページにして4スレッド化。これで精度は大分上がるはず。


あとの課題は複数点出品/落札データの取得かなぁ…。取得自体はできるんだけどどうやって管理するかが面倒くさくなりそう。リンク(さらに多く)をもう一階層増やさなければならないのでそれも面倒だな…


データの方は前回の経験からイベント終了後出品傾向が一段楽するまでに10日程度かかるので、1/中旬あたりを目標に集計しようと思う。