這周除了備戰二級口譯之外,閱讀並實踐了下崔神的《Python3網絡爬蟲開發實戰》,試了下貓眼的排行榜數據和頭條街拍圖片的抓取和保存,充分感受到了python大法的強悍之處。作爲一名python小小白和入坑區塊鏈兩年半的小韭菜,出於好奇心爬了下CoinMarketCap上的歷史記錄,代碼雖短,情深可長,保存在csdn上,說不定以後的以後用得上哈哈哈~之後如果學了數據分析,會把爬出來的數據拿來練習練習!
提醒,要導入的包如下(要記得安裝連接MongoDB吼吼):
import random #用於生成隨機數
import time #用於打印系統時間
from pyquery import PyQuery as pq #用於解析提取所需數據
import requests #用於獲取網頁源碼
from fake_useragent import UserAgent #用於隨機生成user-agent
from openpyxl import workbook # 寫入Excel表所用
from openpyxl import load_workbook # 讀取Excel表所用
import os #用於指定保存路徑
import re #用於提取信息
import pymongo #用於保存數據到mongodb中
第一步:抓“歷史記錄”主頁的核心內容——日期
每頁數據的url規律是https://coinmarketcap.com/zh/historical/+日期,比如2019年3月3日的數據頁url是https://coinmarketcap.com/zh/historical/20190303/,因此,我們需要到“歷史記錄”頁面拿到日期列表。
01.獲取網頁源代碼
def get_one_page(url): #參數爲"歷史記錄"主頁的url鏈接
#爲了不輕易被網站管理人員發現是爬蟲,就僞裝user-agent,模擬真實的瀏覽器去抓服務器響應的內容
ua = UserAgent()
headers = {"User-Agent": ua.random}
#構造請求頭並得到服務器響應結果
response=requests.get(url,headers=headers)
#如果響應結果的狀態碼爲200,說明正常訪問,否則返回none
if response.status_code==200:
#返回響應內容,即網頁源代碼
return response.text #
return None
02.觀察源代碼並獲取所需數據
可以發現,我們所需要的日期數據就在row節點下的href的屬性值中,只要獲取到href再提取下數據就可以拿到日期了。
def getUrlData(html):
#記得導入pyquery庫
doc = pq(html)
#定位到row節點的a標籤
page = doc('.row a')
#遍歷提取href屬性值,並添加到hisdate列表中
hisdate=[]
for data in page.items():
date=data.attr('href')
hisdate.append(date)
return hisdate
#清洗日期數據,獲得讀取數據的日期
def cleanUrlData(list):
#定義一個空列表用於存放清洗後的乾淨數據
clurldata=[]
#遍歷找到任何符合以/zh/historical/開頭的字符串,然後去掉所有非數字,留下的數字便是我們要的數據
for data in list:
if data.startswith('/zh/historical/'):
clurldata.append(re.sub("\D", "", data))
return clurldata #獲取到的乾淨數據可以存到文檔中,之後直接讀取文件就行,我比較懶,直接返回過去,使得每次運行的時候都要先到主頁再去分頁提取數據,不過,因爲日期會更新,所以,看個人喜好啦
第二步:獲取每頁數據,觀察並提取所需數據,清洗後保存
#獲取每頁數據,並保存
def getData(clurldata):
#定義url的起始部分
start_url='https://coinmarketcap.com/zh/historical/'
#這裏臨時定義了一個temp列表,是因爲運行過程中,因爲訪問頻率經常被服務器禁了,沒有去搞代理池的咕涼我於是只能出此下策,哪裏被禁了就把日期改成最後搞定的那一天的日期,然後重新運行(比較傻的方法了吼吼吼)
temp=clurldata[clurldata.index('20140803')+1:]
#然後繼續從被打斷的部分開始抓
for end_url in temp:
#構造最後的html網頁
final_url=start_url+end_url
#獲得網頁源碼
final_html=get_one_page(final_url)
#因爲發現每個數字貨幣的信息都是tr節點開始,因此node在之前全局變量定義:node='tr'
doc = pq(final_html)
page = doc.find(node)
#想把數據分列保存在excel裏,因此建立對應的列表,每讀一頁數據重置一次
index = []
symbol = []
name = []
marketcap = []
price = []
#因爲越到後面,每頁的數據量較多,實際分析用不上,就定義count,最多隻獲取前100的數字貨幣
count=0
#開始遍歷提取這一頁的每個數字貨幣的數據
for data in page.items():
dict = {}
inx = data.find('.text-center').text() #排名
syb = data.find('.currency-symbol.visible-xs').text() #數字貨幣簡寫
nm = data.find('.currency-name-container.link-secondary').text()#數字貨幣名稱
mcap = re.sub(",", "", str(data.find('.no-wrap.market-cap.text-right').text())[1:])#首先去掉開頭的美元符號$,再用re庫去掉逗號(清洗數據)
pri = re.sub(",", "", str(data.find('.price').text())[1:])#一樣先去掉開頭的美元符號$,再用re庫去掉逗號(清洗數據)
#一個個添加到列表中(用於excel保存)
index.append(inx)
symbol.append(syb)
name.append(nm)
marketcap.append(mcap)
price.append(pri)
#添加到字典中(用於MongoDB保存)
dict['index'] = inx
dict['symbol'] = syb
dict['name'] = nm
dict['marketcap'] = mcap
dict['price'] = pri
dict['date'] = end_url
#取前100數據,太多分析價值不大
count+=1
if count==101:
break
# 一條一條地寫進mongodb數據庫中
collection.insert_one(dict)
print(end_url)
#寫進excel表格中
wb = workbook.Workbook() # 創建Excel對象
ws = wb.active # 獲取當前正在操作的表對象
# 寫進excel
for i in range(len(index)):
ws.append([index[i], symbol[i], name[i], marketcap[i], price[i],end_url])
#保存的路徑和名稱
wb.save(data_path+os.path.sep+end_url+ '.xlsx')
print(end_url,'excel success')
#sleep下下,防止被禁,輸出下時間,可以稍微瞭解下實際的隨機等待時間
print("Start : %s" % time.ctime())
time.sleep(random.randint(15, 20))
print("End : %s" % time.ctime())
醬紫就完成數據的抓取啦~有些地方寫得比較笨吼吼~剛入門python一週的咕涼我很多用法還不太熟悉,希望有更好的解決方法的大神多多指教吼吼~去健身啦啦啦~春天到啦,要減肥啦~咕涼我要瘦瘦瘦!
附上完整代碼:
import json
import random
import time
from pyquery import PyQuery as pq
import requests
from fake_useragent import UserAgent
from openpyxl import workbook # 寫入Excel表所用
from openpyxl import load_workbook # 讀取Excel表所用
import os
import re
import pymongo
client=pymongo.MongoClient(host='localhost',port=27017)
db=client.test
collection=db.coinmarketcap
hisdate=[]
node='tr' #目標信息所在節點
data_path= 'CoinMarketCap'+ os.path.sep +'excel'
#如果沒有該路徑,就自動生成對應文件夾
if not os.path.exists(data_path):
os.makedirs(data_path)
def get_one_page(url): #參數爲"歷史記錄"主頁的url鏈接
#爲了不輕易被網站管理人員發現是爬蟲,就僞裝user-agent,模擬真實的瀏覽器去抓服務器響應的內容
ua = UserAgent()
headers = {"User-Agent": ua.random}
#構造請求頭並得到服務器響應結果
response=requests.get(url,headers=headers)
#如果響應結果的狀態碼爲200,說明正常訪問,否則返回none
if response.status_code==200:
#返回響應內容,即網頁源代碼
return response.text #
return None
#獲取後半截url數據
def getUrlData(html):
#記得導入pyquery庫
doc = pq(html)
#定位到row節點的a標籤
page = doc('.row a')
#遍歷提取href屬性值,並添加到hisdate列表中
for data in page.items():
date=data.attr('href')
hisdate.append(date)
return hisdate
#清洗日期數據,獲得後續讀取數據的日期
def cleanUrlData(list):
#定義一個空列表用於存放清洗後的乾淨數據
clurldata=[]
#遍歷找到任何符合以/zh/historical/開頭的字符串,然後去掉所有非數字,留下的數字便是我們要的數據
for data in list:
if data.startswith('/zh/historical/'):
clurldata.append(re.sub("\D", "", data))
return clurldata
#獲取每頁數據,並保存
def getData(clurldata):
#定義url的起始部分
start_url='https://coinmarketcap.com/zh/historical/'
#這裏臨時定義了一個temp列表,是因爲運行過程中,因爲訪問頻率經常被服務器禁了,沒有去搞代理池的咕涼我於是只能出此下策,哪裏被禁了就把日期改成最後搞定的那一天的日期
temp=clurldata[clurldata.index('20150118')+1:]
#然後繼續從被打斷的部分開始抓
for end_url in temp:
#構造最後的html網頁
final_url=start_url+end_url
#獲得網頁源碼
final_html=get_one_page(final_url)
#因爲發現每個數字貨幣的信息都是tr節點開始,因此node在之前全局變量定義:node='tr'
doc = pq(final_html)
page = doc.find(node)
#想把數據分列保存在excel裏,因此建立對應的列表,每讀一頁數據重置一次
index = []
symbol = []
name = []
marketcap = []
price = []
#因爲越到後面,每頁的數據量較多,實際分析用不上,就定義count,最多隻獲取前100的數字貨幣
count=0
#開始遍歷提取這一頁的每個數字貨幣的數據
for data in page.items():
dict = {}
inx = data.find('.text-center').text() #排名
syb = data.find('.currency-symbol.visible-xs').text() #數字貨幣簡寫
nm = data.find('.currency-name-container.link-secondary').text()#數字貨幣名稱
mcap = re.sub(",", "", str(data.find('.no-wrap.market-cap.text-right').text())[1:])#首先去掉開頭的美元符號$,再用re庫去掉逗號(清洗數據)
pri = re.sub(",", "", str(data.find('.price').text())[1:])#一樣先去掉開頭的美元符號$,再用re庫去掉逗號(清洗數據)
#一個個添加到列表中(用於excel保存)
index.append(inx)
symbol.append(syb)
name.append(nm)
marketcap.append(mcap)
price.append(pri)
#添加到字典中(用於MongoDB保存)
dict['index'] = inx
dict['symbol'] = syb
dict['name'] = nm
dict['marketcap'] = mcap
dict['price'] = pri
dict['date'] = end_url
#取前100數據,太多分析價值不大
count+=1
if count==101:
break
# 一條一條地寫進mongodb數據庫中
collection.insert_one(dict)
print(end_url)
#寫進excel表格中
wb = workbook.Workbook() # 創建Excel對象
ws = wb.active # 獲取當前正在操作的表對象
# 寫進excel
for i in range(len(index)):
ws.append([index[i], symbol[i], name[i], marketcap[i], price[i],end_url])
wb.save(data_path+os.path.sep+end_url+ '.xlsx')
print(end_url,'excel success')
#sleep下下,防止被禁,輸出下時間,可以稍微瞭解下實際的隨機等待時間
print("Start : %s" % time.ctime())
time.sleep(random.randint(15, 20))
print("End : %s" % time.ctime())
if __name__ == '__main__':
url = 'https://coinmarketcap.com/zh/historical/'
html = get_one_page(url)
getData(cleanUrlData(getUrlData(html)))
# print(html)