接上篇,這一篇將從技術層面講講是如何實現的。閱讀本文您將會了解如何用python爬取微博的評論以及如何用python word_cloud庫進行數據可視化。
上一篇:程序員代碼下的許豪傑html
打開微博pc m站並找到許豪傑該條微博地址:https://m.weibo.cn/status/413...python
爲何要用m站地址?由於m站能夠直接抓取到api json數據,而pc站雖然也有api返回的是html,相比而言選取m站會省去不少麻煩git
打開該頁面,而且用chrome 的檢查工具 查看network,能夠獲取到評論的api地址。程序員
首先觀察api返回github
從返回地址上能夠看到能夠經過參數page 改變請求的頁碼,而且每頁都回返回總條數和總頁碼數。這裏我決定採用多線程來抓去(其實數據量不大,也能夠單線程跑)。算法
1.存儲選擇mongodb
我這裏選用了MongoDB做爲數據存儲,由於api一般返回的是json數據而json結構和MongoDB的存儲方式能夠結合的很默契,不須要通過任何處理能夠直接的進行插入。chrome
2.防爬蟲數據庫
不少網站可能會作一些防爬蟲的處理,面對同一個請求ip的短期的高頻率請求會進行服務隔斷(直接告訴你服務不可用),這個時候能夠去網上找一些代理進行請求。json
3.多線程的任務分配
採用多線程爬取你固然不能讓多個線程去爬取一樣的連接作別人已經作過的事情,那樣多線程毫無心義。因此你須要制定一套規則,讓不一樣線程爬取不一樣的連接。
# coding=utf-8 from __future__ import division from pymongo import MongoClient import requests import sys import re import random import time import logging import threading import json from os import path import math # 爬取微博評論 # m站微博地址 weibo_url = 'https://m.weibo.cn/status/4132385564040383' thread_nums = 5 #線程數 #代理地址 proxies = { "http": "http://171.92.4.67:9000", "http": "http://163.125.222.240:8118", "http": "http://121.232.145.251:9000", "http": "http://121.232.147.247:9000", } # 建立 日誌 對象 logger = logging.getLogger() handler = logging.StreamHandler() formatter = logging.Formatter( '%(asctime)s %(name)-12s %(levelname)-8s %(message)s') handler.setFormatter(formatter) logger.addHandler(handler) logger.setLevel(logging.DEBUG) mongoconn = MongoClient('127.0.0.1', 27017) mdb = mongoconn.data_analysis das_collection = mdb.weibo weiboid_reobj = re.match(r'.*status/(\d+)', weibo_url) weibo_id = weiboid_reobj.group(1) def scrapy_comments(weibo_id, page): weibo_comment_url = 'https://m.weibo.cn/api/comments/show?id=%s&page=%d' % ( weibo_id, page) res = requests.get(weibo_comment_url) res_obj = json.loads(res.content) return res_obj def import_comments(threadName, weibo_id, page_start, page_end): logger.info('開始線程:%s' % threadName) for page in range(page_start, page_end + 1): logging.info('讀取第%s頁' % page) time.sleep(1) # continue try: res_obj = scrapy_comments(weibo_id, page) logging.info('該頁有%s條記錄' % len(res_obj['data'])) except: logging.error('讀取%s頁時發生錯誤' % page) continue if res_obj['ok'] == 1: comments = res_obj['data'] for comment in comments: comment_text = re.sub( r'</?\w+[^>]*>', '', comment['text']).encode('utf-8') if re.search(r'回覆@.*:', comment_text): # 過濾掉回覆別人的評論 continue comment['text'] = comment_text comment['weibo_id'] = weibo_id logging.info('讀取評論:%s' % comment['id']) try: if das_collection.find_one({'id': comment['id']}): logging.info('在mongodb中存在') else: logging.info('插入記錄:%s' % comment['id']) das_collection.insert_one(comment) except: logging.error('mongodb發生錯誤') else: logging.error('讀取第%s頁時發生錯誤' % page) logging.info('線程%s結束' % threadName) # res_obj = scrapy_comments(weibo_id, page) if __name__ == '__main__': # 分配不一樣連接到不一樣的線程上去 res_obj = scrapy_comments(weibo_id, 1) if res_obj['ok'] == 1: total_number = res_obj['total_number'] logging.info('該條微博有:%s條評論' % total_number) max_page = res_obj['max'] page_nums = math.ceil(max_page / thread_nums) else: raise # print max_page # print page_nums for i in range(1, thread_nums + 1): if i < thread_nums: page_end = page_nums * i else: page_end = max_page page_start = (i - 1) * page_nums + 1 t = threading.Thread(target=import_comments, args=( i, weibo_id, int(page_start), int(page_end))) t.start()
運行腳本完畢,個人MongoDB獲得了2萬多條評論數據,接下來要作的事是對這部分數據進行提取、清洗、結構化等操做。這裏順便說明一下python 數據分析的 大體基本流程。
1.與外界進行交互
這個過程包括數據的獲取、讀取。不論是從網絡資源上爬取、仍是從現有資源(各樣的文件如文本、excel、數據庫存儲對象)
2.準備工做
對數據進行清洗(cleaning)、修整(munging)、整合(combining)、規範化(normalizing)、重塑(reshaping)、切片(slicing)和切塊(dicing)
3.轉換
對數據集作一些數學和統計運算產生新的數據集
4.建模和計算
將數據跟統計模型、機器學習算法或其餘計算工具聯繫起來
5.展現
建立交互式的或靜態的圖片或文字摘要
下面咱們來進行二、3及5的工做:
# coding=utf-8 import sys from pymongo import MongoClient import random # 分詞庫 # from snownlp import SnowNLP import jieba import uniout from collections import Counter, OrderedDict # 詞語云 文本統計可視化庫 from wordcloud import WordCloud mongoconn = MongoClient('127.0.0.1', 27017) mdb = mongoconn.data_analysis das_collection = mdb.weibo total_counts = das_collection.find().count() # random_int = random.randint(0, total_counts - 1) docs = das_collection.find() print docs.count() words_counts = {} for doc in docs: print doc comment_text = doc['text'].encode('utf-8') if len(comment_text) == 0: continue words = jieba.cut(comment_text) for word in words: if word not in words_counts: words_counts[word] = 1 else: words_counts[word] += 1 for word in words_counts.keys(): if words_counts[word] < 2 or len(word) < 2: del words_counts[word] # print words_counts.items() #注意要讓中文不亂碼要指定中文字體 #fit_words 接收參數是dict eg:{'你':333,'好':23} 文字:出現次數 wordcloud = WordCloud( font_path='/Users/cwp/font/msyh.ttf', background_color='white', width=1200, height=1000 ).fit_words(words_counts) import matplotlib.pyplot as plt plt.imshow(wordcloud, interpolation='bilinear') plt.axis("off") plt.show()
介紹下以上代碼:
咱們主要用到了2個工具,jieba和word_cloud。前者對中文進行分詞後者圖形化展現詞語的出現頻率。
衆所周知,中文系的語言處理恐怕是最難的天然語言處理(NLP)的語種。就基本的分詞而言都是一項比較困難的工做,(英語句子中每一個單詞都是有空格分開的,而中文是由單個字組成詞鏈接成串組成句).
舉個例子,請用「孩提」造句,"那個男孩提交完代碼就下班了"。若是人工分詞,能夠知道"男孩"和"提交"應該是分開的2個詞,可是對於機器而言,要辨別"提"應該與"男"仍是"交"進行組詞就很難辦了。要想機器可以更精確的辨別這類問題,就須要讓機器不停學習,讓它知道這種狀況該這麼分而不是那麼分。研究中文天然語言處理將是一個長久而大的工程,對於分析數據(咱們不是要研究天然語言處理😏),這裏就藉助jieba這個庫進行工做了.
對於word_cloud,圖形化文本統計,網上有很多的博文都貼了代碼,但我想說的是我不瞭解它們是否是真的運行出告終果。由於fit_words 這個函數接收的是dict而不是list,官方文檔和函數doc其實寫錯了,在github上有披露。
最後獲得結果:
1.word_cloud A little word cloud generator in Python
3.Requests is the only Non-GMO HTTP library for Python, safe for human consumption.