本文您將
學到的東西包括:
scrapy爬蟲的設置
- requests(一個用來發送HTTP請求的簡單庫)
- BeautifulSoup(一個從HTML和XML中解析數據的庫)
MongoDB的用法
- MongoBooster可視化工具
注意:很多人學Python過程中會遇到各種煩惱問題,沒有人幫答疑容易放棄。為此小編建了個Python全棧免費答疑.裙 :七衣衣九七七巴而五(數字的諧音)轉換下可以找到了,不懂的問題有老司機解決里面還有最新Python教程項目可拿,,一起相互監督共同進步!
Pyecharts可視化工具
re正則表達式庫
- 貪婪模式
- 懶惰模式
系列文章
python爬蟲實戰(1) -- 抓取boss直聘招聘信息
python爬蟲實戰(2) -- MongoDB和數據清洗
python爬蟲實戰(3) -- 數據可視化
實驗內容:使用pyecharts將之前爬取的數據通過圖形化顯示出來
參考:https://segmentfault.com/a/1190000012429530
其實這次沒得參考啦,因為原作者沒寫過程,直接把最后的圖表丟出來了T_T
我先自己研究一下吧~
01 pyecharts初體驗
請教大牛后得知,想要實現這種效果,需要使用pyecharts

於是我使用pip install pyecharts
過程略坎坷,遇到幾次報錯,不太明白,智能重復上述命令,結果兩三次之后,安上了。
跑個代碼實驗一下
import pyecharts bar = pyecharts.Bar(title="myBar",subtitle="xxx data") attr =['a','b','c','d','e','f'] v1 = [1,2,3,4,5,6] v2 = [3,5,2,1,5,1] bar.add('test1',attr,v1,is_stack=True) bar.add('test2',attr,v2,is_stack=True) bar.render()
一實驗發現,能生成html文件,good

但是Jupyter notebook生成的都是空白!類似下面這樣:

這樣可不方便呀,於是百度了很多辦法,終於找到pyecharts的開發者回復的一種解決方案:
安裝之前先執行一次
pip uninstall pyecharts
卸載原有版本后再pip install pyecharts==0.1.9.5
試驗后,發現這個辦法可行,現在Jupyter notebook可以顯示啦~

附上2個參考
1.驚艷的可視化--飛機航行圖 http://python.tedu.cn/know/320402.html
2.pyecharts官方文檔(圖表配置極其強大,什么都有,詞雲、熱力圖、等等) https://pyecharts.readthedocs.io/zh/latest/zh-cn/jupyter_notebook/
http://pyecharts.org/#/zh-cn/jupyter_notebook?id=%E7%A4%BA%E4%BE%8B
02 提取數據並繪制餅圖
先繪制一個工作經驗分布餅圖
代碼如下
experience = ["應屆生","1年以內","1-3年","3-5年","5-10年","10年以","不限"] value = [] for i in range(len(experience)): value.append(db.Python_jobs.count_documents({"experience": experience[i]})) print(value) import pyecharts chart_experience = pyecharts.Pie("工作經驗扇形圖") chart_experience.add('test1',experience,value,is_label_show = True) chart_experience
效果如下

- 主要難點
在於mongodb提取數據的數據庫命令
以及list循環
- 命令小記
len(list) 獲取list元素個數
list.append() 向list中添加新元素
db.collection.count_documents('name':'value') 獲取表中某變量的個數
03 用柱狀圖顯示薪資
實現思路:
1 從數據庫中取出所有應屆生最低工資,累加,除以應屆生數量,得到應屆生最低薪資水平均值,放入salary_low
2 以此類推,循環取出其他工作經驗的最低薪資平均值,放入salary_low中
3 以此類推,得到salary_high,與salary_low計算得到salary_avg
4 通過pyecharts顯示出來
5 其中的數據結構就是list,exp是list,每個工作經驗包含salary_low/avg/high
代碼:
#04 薪資分布柱狀圖 from pyecharts import Bar exp = ["應屆生","1年以內","1-3年","3-5年","5-10年","10年以上","不限"] salary_low = [] salary_high = [] salary_avg = [] i = 0 for i in range(len(exp)): items = db.Python_jobs.find({'experience':exp[i]}) low_sum = 0 high_sum = 0 for item in items: dictionnary = item['salary'] #print(dictionnary) low_sum = dictionnary['low'] + low_sum high_sum = dictionnary['high'] + high_sum try: salary_low.append(round(low_sum/value[i])) salary_high.append(round(high_sum/value[i])) salary_avg.append(round((salary_low[i]+salary_high[i])/2)) except: salary_low.append(round(value[i])) salary_high.append(round(value[i])) salary_avg.append(round(value[i])) #print(salary_low) #print(salary_high) #print(salary_avg) bar = Bar("Python工程師薪資") bar.add("最低薪資", exp, salary_low, is_label_show = True) bar.add("平均薪資", exp, salary_avg, is_label_show = True) bar.add("最高薪資", exp, salary_high, is_label_show = True) bar
實現效果:

04 用扇形圖顯示領域
思路
數據總量 540條招聘信息
一、分幾類(industryField相同算一類)
二、每一類多少條招聘信息
找了很久,終於找到mongodb中的Mapreduce方法可以用來實現
db.Python_jobs.mapReduce( function() { emit(this.industryField,1); }, function(key, values) {return Array.sum(values)}, { out:"non" } )
(執行完上面這條命令,其實把數據存入了另一個collection “non”中
顯示的結果和上面的代碼+find()一樣)
在mongobooster查詢結果如下

對Mapreduce()函數的說明
map: function() {emit(this.cat_id,this.goods_number); }, # 函數內部要調用內置的emit函數,cat_id代表根據cat_id來進行分組,goods_number代表把文檔中的goods_number字段映射到cat_id分組上的數據,其中this是指向向前的文檔的,這里的第二個參數可以是一個對象,如果是一個對象的話,也是作為數組的元素壓進數組里面; reduce: function(cat_id,all_goods_number) {return Array.sum(all_goods_number)}, # cat_id代表着cat_id當前的這一組,all_goods_number代表當前這一組的goods_number集合,這部分返回的就是結果中的value值; out: <output>, # 輸出到某一個集合中,注意本屬性來還支持如果輸出的集合如果已經存在了,那是替換,合並還是繼續reduce? 另外還支持輸出到其他db的分片中,具體用到時查閱文檔,篩選出現的鍵名分別是_id和value; query: <document>, # 一個查詢表達式,是先查詢出來,再進行mapReduce的 sort: <document>, # 發往map函數前先給文檔排序 limit: <number>, # 發往map函數的文檔數量上限,該參數貌似不能用在分片模式下的mapreduce finalize: function(key, reducedValue) {return modifiedObject; }, # 從reduce函數中接受的參數key與reducedValue,並且可以訪問scope中設定的變量 scope: <document>, # 指定一個全局變量,能應用於finalize和reduce函數 jsMode: <boolean>, # 布爾值,是否減少執行過程中BSON和JS的轉換,默認true,true時BSON-->js-->map-->reduce-->BSON,false時 BSON-->JS-->map-->BSON-->JS-->reduce-->BSON,可處理非常大的mapreduce。
pyecharts處理結果如下

代碼如下:
#04.1 數據處理 industryFieldKey = [] industryFieldValue = [] cursor = db.non.find() #這個non就是之前db指令生成的新collection for c in cursor: #如果不用cursor的話,只能看到16進制的游標值 #print(c) industryFieldKey.append(c['_id']) industryFieldValue.append(c['value']) print(industryFieldKey) print(industryFieldValue) #04.2 可視化 from pyecharts import Pie pie = Pie("各領域招聘數量", title_pos='center', width = 1000) pie.add("", industryFieldKey, industryFieldValue, center=[60, 50], radius=[30, 70], label_text_color=None, is_label_show=True, legend_orient='vertical', legend_pos='left') pie
欠缺之處 使用Mapreduce處理的時候沒有排序輸出,所以圖像顯示比較亂
后面有時間再完善吧~
學到的內容:
- Mapreduce 可以統計分組以及各分組數量
- mongodb collection中的內容,需要通過curser循環打印出來
05 用詞雲顯示技術名詞
思路
1 逐個打開頁面
2 爬取label,放入MongoDB中
3 Mapreduce,排序
小發現
之前經常遇到jupyter notebook停止輸出的問題
今天受不了了,google一下發現原來是這樣:
[ * ]表示正在執行
編程[ * ]之后不要再重復敲了,否則就會停止輸出
如果不小心敲了,那就點擊上方欄目上的方塊,停止運行,就好了。

1.逐個打開頁面,print(label)完成 (更新於0801)
tags = soup.find("div", {"class": "job-tags"}) print(tags.text)
效果如下

2.將tags的內容保存到MongoDB中去
問題:取出來的值連在一起,而且存入數據庫時前后都有\n
目前方法:
tags = soup.find("div", {"class": "job-tags"})
print(tags.text)
item['positionLables'] = tags.text
數據庫存儲效果:

研究內容:
如何使用soup.find將網頁中<span>Python</span><span>Hadoop</span>以list形式存入數據庫?
3.使用第二層soup.find,提取list
tags = soup.find("div", {"class": "job-tags"}) lists = tags.find_all("span") print(lists)
效果如下
[<span>python爬蟲</span>, <span>Web前端</span>, <span>Diango</span>]
能夠提取list了,只是還有<span>需要去掉
更新 2018-08-04
從這個列表中提取字符真是搞死我了,這個列表不是普通的列表,里面不是字符串
列表類型是 <class 'bs4.element.ResultSet'>
里面的字符類型是 <class 'bs4.element.Tag'>
所以今天用正則去匹配的時候總是出問題!
如何把 taglists = [<span>python爬蟲</span>, <span>Web前端</span>, <span>Diango</span>]
變成 taglists = ["python爬蟲", "Web前端", "Diango"]
成立難倒我的課題
沒關系,今天學到了正則表達式,也是蠻好的
import re key = r"<span>python爬蟲</span>"#這段是你要匹配的文本 p1 = r"(?<=<span>).+?(?=</span>)"#這是我們寫的正則表達式規則,你現在可以不理解啥意思 pattern1 = re.compile(p1)#我們在編譯這段正則表達式 matcher1 = re.search(pattern1,key)#在源文本中搜索符合正則表達式的部分 print matcher1.group(0)#打印出來
輸出結果
python爬蟲
科普兩個點
- 第一點是?<=與?=
?<=<span> 表示在匹配字符前必須有<span>, ?=</span>表示在匹配字符后必須有</span>
比如 p = r"(?<=A)XX(?=B)"
表示要匹配的字符是XX
但是必須滿足AXXB的形式 - 第二點是+? 貪婪模式和懶惰模式
yiping@hit.edu.cn
p1 = r"@.+." #想匹配@到"."之間,即hit
結果是"@hit.edu."
為什么多了? 因為正則表達式默認是貪婪模式
yiping@hit.edu.cn
p1 = r"@.+?." #在+之后加上?
結果是"@hit."
+?將貪婪模式改成了懶惰模式
放一個正則表達式講的特別好的例子
https://www.cnblogs.com/chuxiuhong/p/5885073.html Python 正則表達式入門(初級篇)
有一本講正則表達式的書挺不錯的 《正則表達式必知必會》
更新 2018-08-09
做出了一周的努力,仍然沒有辦法使用soup find()方法提取崗位label,拖延已久,暫時告一段落吧。
這個項目目前只留下一個詞雲沒有做完,其余內容都過了一遍。
學到的東西包括:
scrapy爬蟲的設置
- requests(一個用來發送HTTP請求的簡單庫)
- BeautifulSoup(一個從HTML和XML中解析數據的庫)
MongoDB的用法
- MongoBooster可視化工具
Pyecharts可視化工具
re正則表達式庫
- 貪婪模式
- 懶惰模式
總結注意:很多人學Python過程中會遇到各種煩惱問題,沒有人幫答疑容易放棄。為此小編建了個Python全棧免費答疑.裙 :七衣衣九七七巴而五(數字的諧音)轉換下可以找到了,不懂的問題有老司機解決里面還有最新Python教程項目可拿,,一起相互監督共同進步!
本文的文字及圖片來源於網絡加上自己的想法,僅供學習、交流使用,不具有任何商業用途,版權歸原作者所有,如有問題請及時聯系我們以作處理。