如何分析部落格中最流行的程式語言

Serge Mosin發表於2017-11-09

摘要:這篇文章我們將對一些各種各樣的部落格的流行度相對於他們在谷歌上的排名進行一個分析。所有程式碼可以在 github 上找到。

如何分析部落格中最流行的程式語言

想法來源

我一直在想,各種各樣的部落格每天到底都有多少頁面瀏覽量,以及在部落格閱讀受眾中最受歡迎的是什麼程式語言。我也很感興趣的是,它們在谷歌的網站排名是否與它們的受歡迎程度直接相關。

為了回答這些問題,我決定做一個 Scrapy 專案,它將收集一些資料,然後對所獲得的資訊執行特定的資料分析和資料視覺化。

第一部分:Scrapy

我們將使用 Scrapy 為我們的工作,因為它為抓取和對該請求處理後的反饋進行管理提供了乾淨和健壯的框架。我們還將使用 Splash 來解析需要處理的 Javascript 頁面。Splash 使用自己的 Web 伺服器充當代理,並處理 Javascript 響應,然後再將其重定向到我們的爬蟲程式。

我這裡沒有描述 Scrapy 的設定,也沒有描述 Splash 的整合。你可以在這裡找到 Scrapy 的示例,而這裡還有 Scrapy+Splash 指南。

獲得相關的部落格

第一步顯然是獲取資料。我們需要關於程式設計部落格的谷歌搜尋結果。你看,如果我們開始僅僅用谷歌自己來搜尋,比如說查詢 “Python”,除了部落格,我們還會得到很多其它的東西。我們需要的是做一些過濾,只留下特定的部落格。幸運的是,有一種叫做 Google 自定義搜尋引擎(CSE)的東西,它能做到這一點。還有一個網站 www.blogsearchengine.org,它正好可以滿足我們需要,它會將使用者請求委託給 CSE,這樣我們就可以檢視它的查詢並重複利用它們。

所以,我們要做的是到 www.blogsearchengine.org 網站,搜尋 “python”,並在一側開啟 Chrome 開發者工具中的網路標籤頁。這截圖是我們將要看到的:

如何分析部落格中最流行的程式語言

突出顯示的是 blogsearchengine 向谷歌委派的一個搜尋請求,所以我們將複製它,並在我們的 scraper 中使用。

這個部落格抓取爬行器類會是如下這樣的:

class BlogsSpider(scrapy.Spider):
    name = 'blogs'
    allowed_domains = ['cse.google.com']

    def __init__(self, queries):
        super(BlogsSpider, self).__init__()
        self.queries = queries

與典型的 Scrapy 爬蟲不同,我們的方法覆蓋了 __init__ 方法,它接受額外的引數 queries,它指定了我們想要執行的查詢列表。

現在,最重要的部分是構建和執行這個實際的查詢。這個過程放在 start_requests 爬蟲的方法裡面執行,我們愉快地覆蓋它:

    def start_requests(self):
        params_dict = {
            'cx': ['partner-pub-9634067433254658:5laonibews6'],
            'cof': ['FORID:10'],
            'ie': ['ISO-8859-1'],
            'q': ['query'],
            'sa.x': ['0'],
            'sa.y': ['0'],
            'sa': ['Search'],
            'ad': ['n9'],
            'num': ['10'],
            'rurl': [
                'http://www.blogsearchengine.org/search.html?cx=partner-pub'
                '-9634067433254658%3A5laonibews6&cof=FORID%3A10&ie=ISO-8859-1&'
                'q=query&sa.x=0&sa.y=0&sa=Search'
            ],
            'siteurl': ['http://www.blogsearchengine.org/']
        }

        params = urllib.parse.urlencode(params_dict, doseq=True)
        url_template = urllib.parse.urlunparse(
            ['https', self.allowed_domains[0], '/cse',
             '', params, 'gsc.tab=0&gsc.q=query&gsc.page=page_num'])
        for query in self.queries:
            for page_num in range(1, 11):
                url = url_template.replace('query', urllib.parse.quote(query))
                url = url.replace('page_num', str(page_num))
                yield SplashRequest(url, self.parse, endpoint='render.html',
                                    args={'wait': 0.5})

在這裡你可以看到相當複雜的 params_dict 字典,它控制所有我們之前找到的 Google CSE URL 的引數。然後我們準備好 url_template 裡的一切,除了已經填好的查詢和頁碼。我們對每種程式語言請求 10 頁,每一頁包含 10 個連結,所以是每種語言有 100 個不同的部落格用來分析。

42-43 行,我使用一個特殊的類 SplashRequest 來代替 Scrapy 自帶的 Request 類。它封裝了 Splash 庫內部的重定向邏輯,所以我們無需為此擔心。十分整潔。

最後,這是解析程式:

    def parse(self, response):
        urls = response.css('div.gs-title.gsc-table-cell-thumbnail') \
            .xpath('./a/@href').extract()
        gsc_fragment = urllib.parse.urlparse(response.url).fragment
        fragment_dict = urllib.parse.parse_qs(gsc_fragment)
        page_num = int(fragment_dict['gsc.page'][0])
        query = fragment_dict['gsc.q'][0]
        page_size = len(urls)
        for i, url in enumerate(urls):
            parsed_url = urllib.parse.urlparse(url)
            rank = (page_num - 1) * page_size + i
            yield {
                'rank': rank,
                'url': parsed_url.netloc,
                'query': query
            }

所有 Scraper 的核心和靈魂就是解析器邏輯。可以有多種方法來理解響應頁面的結構並構建 XPath 查詢字串。您可以使用 Scrapy shell 嘗試並隨時調整你的 XPath 查詢,而不用執行爬蟲。不過我更喜歡視覺化的方法。它需要再次用到谷歌 Chrome 開發人員控制檯。只需右鍵單擊你想要用在你的爬蟲裡的元素,然後按下 Inspect。它將開啟控制檯,並定位到你指定位置的 HTML 原始碼。在本例中,我們想要得到實際的搜尋結果連結。他們的原始碼定位是這樣的:

如何分析部落格中最流行的程式語言

在檢視這個元素的描述後我們看到所找的 <div> 有一個 .gsc-table-cell-thumbnail CSS 類,它是 .gs-title <div> 的子元素,所以我們把它放到響應物件的 css 方法(46 行)。然後,我們只需要得到部落格文章的 URL。它很容易透過'./a/@href' XPath 字串來獲得,它能從我們的 <div> 直接子元素的 href 屬性找到。(LCTT 譯註:此處圖文對不上)

尋找流量資料

下一個任務是估測每個部落格每天得到的頁面瀏覽量。得到這樣的資料有各種方式,有免費的,也有付費的。在快速搜尋之後,我決定基於簡單且免費的原因使用網站 www.statshow.com 來做。爬蟲將抓取這個網站,我們在前一步獲得的部落格的 URL 將作為這個網站的輸入引數,獲得它們的流量資訊。爬蟲的初始化是這樣的:

class TrafficSpider(scrapy.Spider):
    name = 'traffic'
    allowed_domains = ['www.statshow.com']

    def __init__(self, blogs_data):
        super(TrafficSpider, self).__init__()
        self.blogs_data = blogs_data

blogs_data 應該是以下格式的詞典列表:{"rank": 70, "url": "www.stat.washington.edu", "query": "Python"}

請求構建函式如下:

    def start_requests(self):
        url_template = urllib.parse.urlunparse(
            ['http', self.allowed_domains[0], '/www/{path}', '', '', ''])
        for blog in self.blogs_data:
            url = url_template.format(path=blog['url'])
            request = SplashRequest(url, endpoint='render.html',
                                    args={'wait': 0.5}, meta={'blog': blog})
            yield request

它相當的簡單,我們只是把字串 /www/web-site-url/ 新增到 'www.statshow.com' URL 中。

現在讓我們看一下語法解析器是什麼樣子的:

    def parse(self, response):
        site_data = response.xpath('//div[@id="box_1"]/span/text()').extract()
        views_data = list(filter(lambda r: '$' not in r, site_data))
        if views_data:
            blog_data = response.meta.get('blog')
            traffic_data = {
                'daily_page_views': int(views_data[0].translate({ord(','): None})),
                'daily_visitors': int(views_data[1].translate({ord(','): None}))
            }
            blog_data.update(traffic_data)
            yield blog_data

與部落格解析程式類似,我們只是透過 StatShow 示例的返回頁面,然後找到包含每日頁面瀏覽量和每日訪問者的元素。這兩個引數都確定了網站的受歡迎程度,對於我們的分析只需要使用頁面瀏覽量即可 。

第二部分:分析

這部分是分析我們蒐集到的所有資料。然後,我們用名為 Bokeh 的庫來視覺化準備好的資料集。我在這裡沒有給出執行器和視覺化的程式碼,但是它可以在 GitHub repo 中找到,包括你在這篇文章中看到的和其他一切東西。

最初的結果集含有少許偏離過大的資料,(如 google.com、linkedin.com、Oracle.com 等)。它們顯然不應該被考慮。即使其中有些有部落格,它們也不是針對特定語言的。這就是為什麼我們基於這個 StackOverflow 回答 中所建議的方法來過濾異常值。

語言流行度比較

首先,讓我們對所有的語言進行直接的比較,看看哪一種語言在前 100 個部落格中有最多的瀏覽量。

這是能進行這個任務的函式:

def get_languages_popularity(data):
    query_sorted_data = sorted(data, key=itemgetter('query'))
    result = {'languages': [], 'views': []}
    popularity = []
    for k, group in groupby(query_sorted_data, key=itemgetter('query')):
        group = list(group)
        daily_page_views = map(lambda r: int(r['daily_page_views']), group)
        total_page_views = sum(daily_page_views)
        popularity.append((group[0]['query'], total_page_views))
    sorted_popularity = sorted(popularity, key=itemgetter(1), reverse=True)
    languages, views = zip(*sorted_popularity)
    result['languages'] = languages
    result['views'] = views
    return result

在這裡,我們首先按語言(詞典中的關鍵字“query”)來分組我們的資料,然後使用 python 的 groupby 函式,這是一個從 SQL 中借來的奇妙函式,從我們的資料列表中生成一組條目,每個條目都表示一些程式語言。然後,在第 14 行我們計算每一種語言的總頁面瀏覽量,然後新增 ('Language', rank) 形式的元組到 popularity 列表中。在迴圈之後,我們根據總瀏覽量對流行度資料進行排序,並將這些元組展開到兩個單獨的列表中,然後在 result 變數中返回它們。

最初的資料集有很大的偏差。我檢查了到底發生了什麼,並意識到如果我在 blogsearchengine.org 上查詢“C”,我就會得到很多無關的連結,其中包含了 “C” 的字母。因此,我必須將 C 排除在分析之外。這種情況幾乎不會在 “R” 和其他類似 C 的名稱中出現:“C++”、“C”。

因此,如果我們將 C 從考慮中移除並檢視其他語言,我們可以看到如下圖:

如何分析部落格中最流行的程式語言

評估結論:Java 每天有超過 400 萬的瀏覽量,PHP 和 Go 有超過 200 萬,R 和 JavaScript 也突破了百萬大關。

每日網頁瀏覽量與谷歌排名

現在讓我們來看看每日訪問量和谷歌的部落格排名之間的聯絡。從邏輯上來說,不那麼受歡迎的部落格應該排名靠後,但這並沒那麼簡單,因為其他因素也會影響排名,例如,如果在人氣較低的部落格上的文章更新一些,那麼它很可能會首先出現。

資料準備工作以下列方式進行:

def get_languages_popularity(data):
    query_sorted_data = sorted(data, key=itemgetter('query'))
    result = {'languages': [], 'views': []}
    popularity = []
    for k, group in groupby(query_sorted_data, key=itemgetter('query')):
        group = list(group)
        daily_page_views = map(lambda r: int(r['daily_page_views']), group)
        total_page_views = sum(daily_page_views)
        popularity.append((group[0]['query'], total_page_views))
    sorted_popularity = sorted(popularity, key=itemgetter(1), reverse=True)
    languages, views = zip(*sorted_popularity)
    result['languages'] = languages
    result['views'] = views
    return result

該函式接受爬取到的資料和需要考慮的語言列表。我們對這些資料以語言的流行程度進行排序。後來,在類似的語言分組迴圈中,我們構建了 (rank, views_number) 元組(從 1 開始的排名)被轉換為 2 個單獨的列表。然後將這一對列表寫入到生成的字典中。

前 8 位 GitHub 語言(除了 C)是如下這些:

如何分析部落格中最流行的程式語言

如何分析部落格中最流行的程式語言

評估結論:我們看到,所有圖的 PCC (皮爾遜相關係數)都遠離 1/-1,這表示每日瀏覽量與排名之間缺乏相關性。值得注意的是,在大多數圖表(8 箇中的 7 個)中,相關性是負的,這意味著排名的降低會導致瀏覽量的減少。

結論

因此,根據我們的分析,Java 是目前最流行的程式語言,其次是 PHP、Go、R 和 JavaScript。在日常瀏覽量和谷歌排名上,排名前 8 的語言都沒有很強的相關性,所以即使你剛剛開始寫部落格,你也可以在搜尋結果中獲得很高的評價。不過,成為熱門部落格究竟需要什麼,可以留待下次討論。

這些結果是相當有偏差的,如果沒有更多的分析,就不能過分的考慮這些結果。首先,在較長的一段時間內收集更多的流量資訊,然後分析每日瀏覽量和排名的平均值(中值)值是一個好主意。也許我以後還會再回來討論這個。

引用

  1. 抓取:
    1. blog.scrapinghub.com: Handling Javascript In Scrapy With Splash
    2. BlogSearchEngine.org
    3. twingly.com: Twingly Real-Time Blog Search
    4. searchblogspot.com: finding blogs on blogspot platform
  2. 流量評估:
    1. labnol.org: Find Out How Much Traffic a Website Gets
    2. quora.com: What are the best free tools that estimate visitor traffic…
    3. StatShow.com: The Stats Maker

via: https://www.databrawl.com/2017/10/08/blog-analysis/

作者:Serge Mosin 譯者:Chao-zhi 校對:wxy

本文由 LCTT 原創編譯,Linux中國 榮譽推出

相關文章