1 數(shù)據(jù)采集概述

開(kāi)始一個(gè)數(shù)據(jù)分析項(xiàng)目,首先需要做的就是get到原始數(shù)據(jù),獲得原始數(shù)據(jù)的方法有多種途徑。比如:

  1. 獲取數(shù)據(jù)集(dataset)文件

  2. 使用爬蟲(chóng)采集數(shù)據(jù)

  3. 直接獲得excel、csv及其他數(shù)據(jù)文件

  4. 其他途徑…

本次福布斯系列數(shù)據(jù)分析項(xiàng)目實(shí)戰(zhàn),數(shù)據(jù)采集方面,主要數(shù)據(jù)來(lái)源于使用爬蟲(chóng)進(jìn)行數(shù)據(jù)采集,同時(shí)也輔助其他數(shù)據(jù)進(jìn)行對(duì)比。

本文主要是介紹使用爬蟲(chóng)進(jìn)行數(shù)據(jù)采集的思路和步驟。

本次采集的福布斯全球上市企業(yè)2000強(qiáng)排行榜數(shù)據(jù),涉及年份從2007年到2017年,跨越10多年。

本次采集的目標(biāo)網(wǎng)站,是多個(gè)網(wǎng)頁(yè),但多個(gè)網(wǎng)頁(yè)的分布結(jié)構(gòu)都有所不同,雖然思路和步驟都差不多,但需要分開(kāi)來(lái)編寫(xiě),分別采集。

2 數(shù)據(jù)采集步驟

數(shù)據(jù)采集大體分為幾步:

  1. 目標(biāo)主網(wǎng)頁(yè)內(nèi)容的Download

  2. 主網(wǎng)頁(yè)上數(shù)據(jù)的采集

  3. 主網(wǎng)頁(yè)上其他分發(fā)頁(yè)面網(wǎng)站鏈接的采集

  4. 各分發(fā)網(wǎng)頁(yè)數(shù)據(jù)的download與采集

  5. 將采集的數(shù)據(jù)保存

涉及到的python庫(kù)包括,requests、BeautifulSoup以及csv。 下面以采集某年的數(shù)據(jù)為案例,來(lái)描述下數(shù)據(jù)采集的步驟。

import requestsfrom bs4 import BeautifulSoupimport csv

2.1 數(shù)據(jù)Download模塊

主要是基于 requests,代碼如下:

def download(url):
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36'}
    response = requests.get(url,headers=headers)    # print(response.status_code)
    return response.text

這個(gè)模塊會(huì)在主網(wǎng)頁(yè)數(shù)據(jù)下載,以及各個(gè)分頁(yè)面數(shù)據(jù)下載時(shí)使用,是一個(gè)比較通用的模塊。

2.2 主網(wǎng)頁(yè)上數(shù)據(jù)的采集

主網(wǎng)頁(yè)的頁(yè)面結(jié)構(gòu),主要分為兩個(gè)部分,一類是包含其他頁(yè)面數(shù)據(jù)的網(wǎng)頁(yè)鏈接,一類是主網(wǎng)頁(yè)上的公司數(shù)據(jù)列表,以表格形式在網(wǎng)頁(yè)上顯示。

用BeautifulSoup可以把這些數(shù)據(jù)解析出來(lái)。 代碼模塊如下:

  • 解析主網(wǎng)頁(yè)上的公司數(shù)據(jù)列表信息

def get_content_first_page(html, year):
    '''
    獲取排名在1-100的公司列表,且包含表頭
    '''
    soup = BeautifulSoup(html, 'lxml')
    body = soup.body
    body_content = body.find('div', {'id': 'bodyContent'})
    tables = body_content.find_all('table', {'class': 'XXXXtable'})    # tables一共有3個(gè),最后一個(gè)才是我們想要的
    trs = tables[-1].find_all('tr')    # 獲取表頭名稱
    # trs[1], 這里跟其他年份不一樣
    row_title = [item.text.strip() for item in trs[1].find_all('th')]
    row_title.insert(0, '年份')

    rank_list = []
    rank_list.append(row_title)    for i, tr in enumerate(trs):        if i == 0 or i == 1:            continue
        tds = tr.find_all('td')        # 獲取公司排名及列表
        row = [ item.text.strip() for item in tds]
        row.insert(0, year)
        rank_list.append(row)    return rank_list
  • 解析主網(wǎng)頁(yè)上其他頁(yè)面的網(wǎng)頁(yè)鏈接

def get_page_urls(html):
    '''
    獲取排名在101-2000的公司的網(wǎng)頁(yè)鏈接
    '''
    soup = BeautifulSoup(html, 'lxml')
    body = soup.body
    body_content = body.find('div', {'id': 'bodyContent'})
    label_div = body_content.find('div', {'align':'center'})
    label_a = label_div.find('p').find('b').find_all('a')

    page_urls = ['basic_url' + item.get('href') for item in label_a]    return page_urls

2.3 各個(gè)分發(fā)頁(yè)面上的數(shù)據(jù)采集

步驟也是 網(wǎng)頁(yè)頁(yè)面下載 和表格類數(shù)據(jù)爬取。 代碼內(nèi)容跟主網(wǎng)頁(yè)頁(yè)面類似,只是細(xì)節(jié)上有些差異,這里就不作贅述了。

2.4 數(shù)據(jù)存儲(chǔ)

采集的數(shù)據(jù),最后保存到csv文件中。模塊代碼如下:

def save_data_to_csv_file(data, file_name):
    '''
    保存數(shù)據(jù)到csv文件中
    '''
    with open(file_name, 'a', errors='ignore', newline='') as f:
        f_csv = csv.writer(f)
        f_csv.writerows(data)

2.5 數(shù)據(jù)采集主函數(shù)

def get_forbes_global_year_2007(year=2007):
    url = 'url'
    html = download(url)    # print(html)

    data_first_page = get_content_first_page(html, year)    # print(data_first_page)
    save_data_to_csv_file(data_first_page, 'forbes_'+str(year)+'.csv')

    page_urls = get_page_urls(html)    # print(page_urls)

    for url in page_urls:
        html = download(url)
        data_other_page = get_content_other_page(html, year)        # print(data_other_page)
        print('saving data ...', url)
        save_data_to_csv_file(data_other_page, 'forbes_'+str(year)+'.csv')if __name__ == '__main__':    # get data from Forbes Global 2000 in Year 2009
    get_forbes_global_year_2007()

3 總結(jié)

本文只介紹了數(shù)據(jù)采集的思路與各個(gè)模塊,并沒(méi)有提供目標(biāo)網(wǎng)頁(yè)的鏈接, 一方面由于原始網(wǎng)頁(yè)的數(shù)據(jù)信息比較雜亂,采集的時(shí)候需要寫(xiě)多個(gè)采集程序,另外一方面,由于我們的重點(diǎn)在于后續(xù)的數(shù)據(jù)分析部分,希望不要著重于數(shù)據(jù)爬取。

在后續(xù)的分析過(guò)程中,我們會(huì)來(lái)查看數(shù)據(jù)的結(jié)構(gòu)、數(shù)據(jù)完整性及相關(guān)信息,歡迎關(guān)注微信公眾號(hào)(ID:PyDataRoad)。

本期推薦閱讀:

作者:Lemon 
出處:個(gè)人微信公眾號(hào):“Python數(shù)據(jù)之道”(ID:PyDataRoad)和博客園:http://www.cnblogs.com/lemonbit/ 
本文版權(quán)歸作者所有,歡迎轉(zhuǎn)載,但未經(jīng)作者同意必須保留此段聲明,且在文章頁(yè)面明顯位置給出原文出處,否則保留追究法律責(zé)任的權(quán)利。

分類: Python

http://www.cnblogs.com/lemonbit/p/7220319.html