価格監視ツールとしてのR

この記事では、競合他社の監視などのトピックに触れたいと思います。 このトピックには多くのサポーターがいることを理解しています。ほとんどの企業の成功した開発には何らかの形で監視が必要であり、モニターからビジネスの利益を守る反対者だからです。



競争市場で何らかの形で販売に関係している人は、競合他社を監視することが重要なタスクであることをおそらく知っているでしょう。 結果は、ローカル価格設定と品揃えポリシーの変更から会社の発展のための戦略的計画の作成まで、まったく異なる目的に使用されます。 著者は、この問題の解決を実践し、ロシア最大の電子小売業者の1つを監視することにしました。 それの由来-



導入する代わりに



この記事では、ソーシャルエンジニアリングの方法について説明したり、監視サービスを提供している企業とやり取りしたりすることはありません。 また、モニタリング分析の説明はなく、収集アルゴリズムと操作中に遭遇しなければならないいくつかの困難のみを追加します。 最近、著者はRをますます使用しており、それを使用してデータを収集することが決定されました。 さらに、オープンデータ(たとえば、 hereherehere )はますます人気が高まっており、使用する環境から直接データを操作するスキルが役立ちます。 すべての行動は本質的に実証的であり、結果のメロンは誰にも譲渡されませんでした。



サイト分析



最初に行うことは、調査対象の競合他社のサイト構造を調査することです。 コンテンツから始めましょう。 商品分類にはいくつかのレベルがあり、どの製品のレベル数も常に同じです。 商品のリストには、レベル2またはレベル3からアクセスできます。さらに作業を進めるために、レベル2を使用することにしました。

次のステップは、必要な製品のリストを含むページのソースコードを調べ、その構造を調べることでした。 各アイテムは個別のHTMLコンテナにあります。 ここで最初の難しさが待っています-ページコードにはリストの最初の30製品のみに関する情報が含まれています-これが私たちに合わないことは明らかです。 著者は、次の30の製品をプログラムで表示する方法を理解していなかったため、モバイルバージョンのサイトを検討することにしました。 ページの下部にあるモバイル版では、次のページと最後のページへのリンクがあります。 さらに、サイトのモバイルバージョンは、不要なリンクやタグが「散らばる​​」ことがはるかに少なくなります。



コードを書く



最初に、コードをいくつかのコンポーネントに分割することが決定されました。

1.特定のページから情報を収集する機能。 最大15の製品がある特定のページのURLを受け入れます(モバイルバージョンとの違い)。 この関数は、商品の入手可能性、名前、記事、レビュー数、価格に関する情報を含むdata.frameを返します。

最初の機能
getOnePageBooklet <- function(strURLsub="", curl=getCurlHandle()){ # loading the required page html <- getURL(strURLsub, .encoding='UTF-8', curl=curl) # parsing html html.raw <- htmlTreeParse( html, useInternalNodes=T ) # searching for SKU nodes html.parse.SKU <- xpathApply(html.raw, path="//section[@class='b-product']", fun=xmlValue) # some regex :) noT <- gsub(' ([0-9]+)\\s([0-9]+) ',' \\1\\2 ',unlist(html.parse.SKU)) noT <- gsub(';',',',noT) noT <- gsub('\r\n',';',noT) noT <- trim(noT) noT <- gsub("(\\s;)+", " ", noT) noT <- gsub("^;\\s ", "", noT) noT <- gsub(";\\s+([0-9]+)\\s+;", "\\1", noT) noT <- gsub(" ; ", "", noT) noT <- gsub(" ", "", noT) noT <- gsub("\\s+;\\s*", "", noT) noT <- gsub("\\s+.;\\s*", "", noT) noT <- gsub(";\\s+", ";", noT) # text to list not.df <- strsplit(noT,';') # list to nice df tryCatch( not.df <- as.data.frame(matrix(unlist(not.df), nrow = length(not.df), byrow = T)), error=function(e) {print(strURLsub)} ) }
      
      







2.機能1を使用して、商品分類の特定のレベルのすべてのページから情報を収集する機能。 この関数の主なポイントは、最後のページの番号を見つけ、関数1を使用して最初から最後に移動し、結果を1つのdata.frameに結合することです。 この関数の結果は、このレベルの商品分類子のすべての商品を含むdata.frameです。

第二の機能
 getOneBooklet <- function(strURLmain="", curl=getCurlHandle()){ # data frane for the result df <- data.frame(inStock=character(), SKU=character(), Article=numeric(), Comment=numeric(), Price=numeric()) # loading main subpage html <- getURL(strURLmain, .encoding='UTF-8', curl=curl) # parsing main subpage html.raw <- htmlTreeParse( html, useInternalNodes=T ) # finding last subpage html.parse.pages <- xpathApply(html.raw, path="//a[@class='page g-nouline']", fun=xmlValue) if(length(html.parse.pages)==0){ urlMax <- 1 }else{ urlMax <- as.numeric(unlist(html.parse.pages)[length(unlist(html.parse.pages))]) } # loop for all sybpages tryCatch( for(iPage in 1:urlMax){ strToB <- paste0(strURLmain, '?pageNum=',iPage) df.inter <- getOnePageBooklet(strToB, curl) df <- rbind(df, df.inter) }, error=function(e) {print(iPage)}) # write.table(df, paste0('D:\\', as.numeric(Sys.time()) ,'.csv'), sep=";") df }
      
      







3.機能2を使用して、商品分類子の使用可能なすべてのレベルから情報を収集する機能。 さらに、取得したデータに分類子レベル名が追加されます。 念のため、あるカテゴリの情報が完全に収集されると、結果がディスクに保存されます。

第三の機能
 getOneCity <- function(urlMain = "http://m.tramlu.ru", curl = getCurlHandle()){ df.prices <- data.frame(inStock = character(), SKU = character(), Article = numeric(), Comment = numeric(), Price = numeric(), level1 = character(), level2 = character()) level1 <- getAllLinks(urlMain, curl) numLevel1 <- length(level1[,2]) for (iLevel1 in 1:numLevel1){ strURLsubmain <- paste0(urlMain, level1[iLevel1, 2]) level2 <- getAllLinks(strURLsubmain, curl) numLevel2 <- length(level2[,2]) for (iLevel2 in 1:numLevel2){ strURLsku <- paste0(urlMain, level2[iLevel2,2]) df.temp <- getOneBooklet(strURLsku, curl) df.temp$level1 <- level1[iLevel1,1] df.temp$level2 <- level2[iLevel2,1] df.prices <- rbind(df.prices, df.temp) } write.table(df.prices, paste0('D:\\', iLevel1 ,'.csv'), sep=";", quote = FALSE) } df.prices }
      
      







その後、禁止ハンマーにbyえたため、プロキシを使用して別の機能を追加する必要がありました。 その後、誰も禁止することさえできなかったことが判明し、スクリプトのテストを考慮して分類器全体が問題なく組み立てられたため、すべてが使用されなかった100個のプロキシに関する情報を含むdata.frameの作成に限定されました。

プロキシリストの取得
 getProxyAddress <- function(){ htmlProxies <- getURL('http://www.google-proxy.net/', .encoding='UTF-8') #htmlProxies <- gsub('</td></tr>',' \n ', htmlProxies) htmlProxies <- gsub('\n','', htmlProxies) htmlProxies <- gsub('(</td><td>)|(</td></tr>)',' ; ', htmlProxies) # parsing main subpage htmlProxies.raw <- htmlTreeParse( htmlProxies, useInternalNodes=T ) # finding last subpage html.parse.proxies <- xpathApply(htmlProxies.raw, path="//tbody", fun=xmlValue) html.parse.proxies<- gsub('( )+','', html.parse.proxies) final <- unlist(strsplit(as.character(html.parse.proxies),';')) final <- as.data.frame(matrix(final[1:800], nrow = length(final)/8, ncol = 8, byrow=T)) #final <- gsub('( )+','', final) names(final) <- c('IP','Port','Code','Country','Proxy type','Google','Https','Last checked') sapply(final, as.character) }
      
      







このようなプロキシを使用できます

プロキシの使用方法
 opts <- list( proxy = "1.1.1.1", proxyport = "8080" ) getURL("http://habrahabr.ru", .opts = opts)
      
      







コードのすべてのコンポーネントの構造は似ています。 RCurlパッケージのgetURL関数、 htmlTreeParse 、およびXMLパッケージのxpathApplyおよびいくつかの正規表現が使用されます。

最後の難しさは、価格を知りたい都市を示すことでした。 デフォルトでは、データをロードする際に、商品の未定義の在庫があるメール配送価格に関する情報が提供されていました。 調査中の会社のサイトに入ると、都市の場所を選択するように促すウィンドウが表示されます。 この情報はブラウザのCookieに保存され、選択した都市の価格と製品の表示に使用されます。 RがCookieを保存するには、使用する接続のプロパティを設定する必要があります。 次に、関心のある都市に対応するページをRにロードするだけです。

接続プロパティ
 agent ="Mozilla/5.0" curl = getCurlHandle() curlSetOpt(cookiejar="cookies.txt", useragent = agent, followlocation = TRUE, curl=curl)
      
      







結論の代わりに



必要なパラメーターを設定したら、機能3を開始し、約30分待って、調査中のサイトのすべての商品とカテゴリのリストを取得します。 モスクワ市の価格は60,000以上でした。 結果は、data.frameおよびディスクに保存されたいくつかのファイルとして表示されます。

スクリプト全体がGitHubにあります



ご清聴ありがとうございました。



All Articles