爬蟲(chóng)爬取網(wǎng)頁(yè)信息的思路:發(fā)送網(wǎng)頁(yè)端請(qǐng)求—>獲取響應(yīng)內(nèi)容—>解析內(nèi)容—> 獲取想要的數(shù)據(jù)—>保存數(shù)據(jù)
這次我們要實(shí)現(xiàn)的是爬取靜態(tài)網(wǎng)頁(yè)的股票數(shù)據(jù),首先是獲取滬深A(yù)股的所有股票代碼,再用這些股票代碼獲取相應(yīng)股票的信息
東方財(cái)富網(wǎng)有所有個(gè)股的股票代碼(滬深A(yù)股所有股票)
查看其網(wǎng)頁(yè)源代碼
在網(wǎng)頁(yè)源代碼中可以搜索到相應(yīng)的元素,判斷其是數(shù)據(jù)是靜態(tài)的
接下來(lái)是獲取每只個(gè)股的信息,由于周六日沒(méi)開(kāi)市,東方財(cái)富網(wǎng)的個(gè)股信息沒(méi)有顯示
這里改用百度股市通(個(gè)股)
同樣地檢查元素可以發(fā)現(xiàn)個(gè)股的信息也是靜態(tài)的
準(zhǔn)備工作:通過(guò)pip導(dǎo)入beautifulsoup4模塊
查看python目錄下的文件 scripts/easy_install 存不存在
如果存在執(zhí)行 easy_install.exe pip
安裝成功后執(zhí)行 pip install beautifulsoup4
首先獲取所有股票的列表
一、獲取東方財(cái)富網(wǎng)股票列表的網(wǎng)頁(yè)源代碼:
#- -coding:utf-8 - -
from urllib import request
對(duì)于python 3來(lái)說(shuō),urllib是一個(gè)非常重要的一個(gè)模塊 ,可以非常方便的模擬瀏覽器訪(fǎng)問(wèn)互聯(lián)網(wǎng),對(duì)于python 3 爬蟲(chóng)來(lái)說(shuō), urllib更是一個(gè)必不可少的模塊,它可以幫助我們方便地處理URL.
urllib.request是urllib的一個(gè)子模塊,可以打開(kāi)和處理一些復(fù)雜的網(wǎng)址
from bs4 import BeautifulSoup
Beautiful Soup將復(fù)雜HTML文檔轉(zhuǎn)換成一個(gè)復(fù)雜的樹(shù)形結(jié)構(gòu),每個(gè)節(jié)點(diǎn)都是Python對(duì)象,所有對(duì)象可以歸納為4種:Tag、NavigableString、BeautifulSoup、Comment|**
模擬瀏覽器爬取信息
在訪(fǎng)問(wèn)某些網(wǎng)站的時(shí)候,網(wǎng)站通常會(huì)用判斷訪(fǎng)問(wèn)是否帶有頭文件來(lái)鑒別該訪(fǎng)問(wèn)是否為爬蟲(chóng),用來(lái)作為反爬取的一種策略。
Python中urllib中的request模塊提供了模擬瀏覽器訪(fǎng)問(wèn)的功能
url=r'http://quote.eastmoney.com/stocklist.html'
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}
page = request.Request(url, headers=headers)
其中headers是一個(gè)字典,通過(guò)這種方式可以將爬蟲(chóng)模擬成瀏覽器對(duì)網(wǎng)站進(jìn)行訪(fǎng)問(wèn)。
page_info=request.urlopen(page).read()
urllib.request.urlopen()方法實(shí)現(xiàn)了打開(kāi)url,并返回一個(gè) http.client.HTTPResponse對(duì)象,通過(guò)http.client.HTTPResponse的read()方法,獲得response body,轉(zhuǎn)碼最后通過(guò)print()打印出來(lái).
page_info=page_info.decode('GB2312',errors='ignore')
decode('GB2312',errors='ignore')用來(lái)將頁(yè)面轉(zhuǎn)換成GB2312-8的編碼格式,否則會(huì)出現(xiàn)亂碼,編碼的格式取決于網(wǎng)頁(yè)的編碼形式,可在網(wǎng)頁(yè)源代碼head查看
獲得網(wǎng)頁(yè)的html代碼后,自然就是要將我們所需要的部分從雜亂的html代碼中分離出來(lái)。這里#使用Python中一種比較友好且易用的數(shù)據(jù)提取方式——BeautifulSoup
soup=BeautifulSoup(page_info,'html.parser')
將獲取到的內(nèi)容轉(zhuǎn)換成BeautifulSoup格式,并將html.parser作為解析器,這是Python標(biāo)準(zhǔn)庫(kù)中的解析器
用開(kāi)發(fā)者查看網(wǎng)頁(yè)源碼發(fā)現(xiàn)股票代碼包含在
標(biāo)簽中
股票代碼
由于百度股市通個(gè)股的網(wǎng)址信息使用的是完整的股票代碼,深圳交易所的代碼以sz開(kāi)頭,上海交易所的代碼以sh開(kāi)頭,股票的數(shù)字有6位構(gòu)成,因此我們要從a標(biāo)簽的鏈接中獲取股票代碼,而不是直接獲取a標(biāo)簽的文本數(shù)據(jù)。
#從獲取的內(nèi)容中找到所有a標(biāo)簽
cnt=soup.find_all('a')
import re
#儲(chǔ)存完整股票代碼
lst=[]
#for循環(huán)歷遍獲取的a標(biāo)簽
for i in cnt:
try:
#獲取a標(biāo)簽中的鏈接
href=i.attrs['href']
#正則表達(dá)式提取完整的股票代碼
lst.append(re.findall(r'[s][hz]\d{6}',href)[0])
#這里[0]的作用是把獲取到的列表轉(zhuǎn)化為字符串添加到列表中
except:
continue
對(duì)文件操作,把獲取的股票代碼列表寫(xiě)入文檔中,打開(kāi)的文件一定要關(guān)閉,否則會(huì)占用相當(dāng)大的系統(tǒng)資源,python中的with語(yǔ)句可以幫我們自動(dòng)調(diào)用close()而不需要我們寫(xiě)出來(lái),'w'以只寫(xiě)的方式打開(kāi)文件,如果文件存在的話(huà)會(huì)先刪除再重新創(chuàng)建
#寫(xiě)入D盤(pán)d.txt文件
with open(r'D:d.txt','w') as file:
file.write(str(lst))
二、獲取股票信息
首先查看股票信息的網(wǎng)頁(yè)源碼
個(gè)股信息
百度股票網(wǎng)的網(wǎng)址為:由于平臺(tái)文章限制請(qǐng)自行查找
個(gè)股信息的網(wǎng)址為:由于平臺(tái)文章限制請(qǐng)自行查找
想要獲取每只個(gè)股的網(wǎng)址只需要?dú)v遍股票代碼列表,再與首頁(yè)網(wǎng)址拼接即可,代碼如下
stockUrl='https://gupiao.baidu.com/stock/'
接下來(lái)是通過(guò)網(wǎng)址獲取網(wǎng)頁(yè)html數(shù)據(jù),解析獲取股票信息
#歷遍股票代碼列表構(gòu)造個(gè)股網(wǎng)址
count=0
for stock in lst:
url=stockUrl+stock+'.html'
try:
#獲取個(gè)股網(wǎng)頁(yè)html代碼
page = request.Request(url, headers=headers)
page_info=request.urlopen(page).read()
page_info=page_info.decode('utf-8','ignore').replace(u'\xa9', u'')
#直接解碼這里會(huì)報(bào)錯(cuò),原因是?不能直接解碼,這里將?替換成空格
if page_info=='':
continue
#解析網(wǎng)頁(yè)內(nèi)容
soup=BeautifulSoup(page_info,'html.parser')
#字典儲(chǔ)存股票信息
infoDict = {}
#查找包含個(gè)股信息的div標(biāo)簽
stockInfo = soup.find('div',attrs={'class':'stock-bets'})
#查找股票名字存入字典
name = stockInfo.find_all(attrs={'class':'bets-name'})[0]
infoDict.update({'股票名稱(chēng)': name.text.split()[0]})
#split()對(duì)字符串進(jìn)行切片,去除后面的空格
#股票的其他信息存放在
dt
和
dd
標(biāo)簽中,查找標(biāo)簽
keyList = stockInfo.find_all('dt')
valueList = stockInfo.find_all('dd')
#把獲得的鍵和值按鍵值對(duì)的方式村放入字典中
for i in range(len(keyList)):
key = keyList[i].text
val = valueList[i].text
infoDict[key] = val
#字典中的個(gè)股信息寫(xiě)入文本文件中
with open(r'D:f.txt', 'w') as f:
f.write( str(infoDict) + '\n' )
count = count + 1
#打印當(dāng)前進(jìn)度
print("\r當(dāng)前進(jìn)度: {:.2f}%".format(count
100/len(lst)),end="")
except:
count = count + 1
print("\r當(dāng)前進(jìn)度: {:.2f}%".format(count
100/len(lst)),end="")
continue
由于股票信息太多,這里只爬取其中一百只股票的信息
爬取結(jié)果如下:
整個(gè)實(shí)現(xiàn)過(guò)程的完整代碼如下:
from urllib import request
from bs4 import BeautifulSoup
url = r'http://quote.eastmoney.com/stocklist.html'
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.87 Safari/537.36'}
page = request.Request(url, headers=headers)
page_info=request.urlopen(page).read()
page_info=page_info.decode('GB2312',errors='ignore')
soup=BeautifulSoup(page_info,'html.parser')
cnt=soup.find_all('a')
import re
lst=[]
for i in cnt:
try:
href=i.attrs['href']
lst.append(re.findall(r'[s][hz]\d{6}',href)[0])
except:
continue
stockUrl='https://gupiao.baidu.com/stock/'
count=0
headers={'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/67.0.3396.99 Safari/537.36'}
for stock in lst[350:400]:
url=stockUrl+stock+'.html'
try:
page = request.Request(url, headers=headers)
page_info=request.urlopen(page).read()
page_info=page_info.decode('utf-8','ignore').replace(u'\xa9', u'')
if page_info=='':
continue
soup=BeautifulSoup(page_info,'html.parser')
infoDict = {}
stockInfo = soup.find('div',attrs={'class':'stock-bets'})
name = stockInfo.find_all(attrs={'class':'bets-name'})[0]
infoDict.update({'股票名稱(chēng)': name.text.split()[0]})
keyList = stockInfo.find_all('dt')
valueList = stockInfo.find_all('dd')
for i in range(len(keyList)):
key = keyList[i].text
val = valueList[i].text
infoDict[key] = val
with open(r'D:f.txt', 'a') as f:
f.write( str(infoDict) + '\n' )
count = count + 1
print("\r當(dāng)前進(jìn)度: {:.2f}%".format(count
100/len(lst[:100])),end="")
except:
count = count + 1
print("\r當(dāng)前進(jìn)度: {:.2f}%".format(count
100/len(lst[:100])),end="")
continue
更多文章、技術(shù)交流、商務(wù)合作、聯(lián)系博主
微信掃碼或搜索:z360901061

微信掃一掃加我為好友
QQ號(hào)聯(lián)系: 360901061
您的支持是博主寫(xiě)作最大的動(dòng)力,如果您喜歡我的文章,感覺(jué)我的文章對(duì)您有幫助,請(qǐng)用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點(diǎn)擊下面給點(diǎn)支持吧,站長(zhǎng)非常感激您!手機(jī)微信長(zhǎng)按不能支付解決辦法:請(qǐng)將微信支付二維碼保存到相冊(cè),切換到微信,然后點(diǎn)擊微信右上角掃一掃功能,選擇支付二維碼完成支付。
【本文對(duì)您有幫助就好】元
