实例分析
淘宝爬虫实例分析
功能描述
目标:获取淘宝搜索页面的信息,提取其中的商品名称和价格
解决的问题:
淘宝的搜索接口
翻页的处理
使用requests与re库
在淘宝中搜索书包后
起始页
https://s.taobao.com/search?q=书包&js=1&stats_click=search_radio_all%
3A1&initiative_id=staobaoz_20170105&ie=utf8
“书包”
第二页
https://s.taobao.com/search?q=书包&js=1&stats_click=search_radio_all%
3A1&initiative_id=staobaoz_20170105&ie=utf8&bcoffset=0&ntoffset=0&p4pp
ushleft=1%2C48&s=44
第三页
https://s.taobao.com/search?q=书包&js=1&stats_click=search_radio_all%
3A1&initiative_id=staobaoz_20170105&ie=utf8&bcoffset=‐3&ntoffset=‐
3&p4ppushleft=1%2C48&s=88
可看出每页展示44个商品。以此特征进行翻页处理
main函数
def main():
goods = '书包'
depth = 3
start_url = 'https://s.taobao.com/search?q=' + goods
infoList = []
for i in range(depth):
try:
url = start_url + '&s=' + str(44*i)
html = getHTMLText(url)
parsePage(infoList, html)
except:
continue
printGoodsList(infoList)
getHTMLText函数
def getHTMLText(url):
try:
r = requests.get(url, timeout=30)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except:
return ""
parsePage函数
def parsePage(ilt, html):
try:
plt = re.findall(r'\"view_price\"\:\"[\d\.]*\"',html)
tlt = re.findall(r'\"raw_title\"\:\".*?\"',html)
for i in range(len(plt)):
price = eval(plt[i].split(':')[1])
title = eval(tlt[i].split(':')[1])
ilt.append([price , title])
except:
print("")
printGoodsList函数
def printGoodsList(ilt):
tplt = "{:4}\t{:8}\t{:16}"
print(tplt.format("序号", "价格", "商品名称"))
count = 0
for g in ilt:
count = count + 1
print(tplt.format(count, g[0], g[1]))
但淘宝已经禁用爬虫,故爬取无结果
但代码值得学习。
爬取股票有关信息
使用模块
requests-bs4-re库
候选网站
新浪股票:
http://finance.sina.com.cn/stock/
百度股票:
https://gupiao.baidu.com/stock/
选取原则: 股票信息静态存在于HTML页面中,非js代码生成
没有Robots协议限制
选取方法: 浏览器F12,源代码查看等
选取心态: 不要纠结于某个网站,多找信息源尝试
通过网站代码发现新浪的数据是动态的不适合爬取,顾轩泽百度股票
数据网站的确定
获取股票列表:
东方财富网:http://quote.eastmoney.com/stocklist.html
获取个股信息:
百度股票:https://gupiao.baidu.com/stock/
单个股票:https://gupiao.baidu.com/stock/sz002439.html
程序结构设计
步骤1: 从东方财富网获取股票列表
步骤2: 根据股票列表逐个到百度股票获取个股信息
步骤3: 将结果存储到文件
实例编写
main()函数
输入url并且输入文件储存路径,调用相关函数
getHTMLText()函数
获得url中的html信息
getStockList()函数
获得东方财富网中想要的那串数字,用于指引到百度股票中的搜索
getStockInfo()函数
在百度股票中检索到相关信息并存储。
全代码
import requests
import re
from bs4 import BeautifulSoup
import traceback #用于错误检索
def getHTMLText(url):
try:
r=requests,get(url)
r.raise_for_status()
r.encoding=r.apparent_encoding
return r.text
except:
return ""
def getStockList(lst,stockURL):
html=getHTMLText(stockURL)
soup=BeautifulSoup(html,'html.parser')
a=soup.find_all('a')
for i in a:
try:
href=i.attr['href']
lst.append(re.findall(r"[s][hz]\d{6}", href)[0])
except:
continue
def getStockInfo(lst,stockURL,fpath):
for stock in lst:
url=stockURL+stock+".html"
html=getHTMLText(url)
try:
if html=="":
continue
infoDict={}
soup=BeautifulSoup(html,'parser')
stockInfo=soup.find('div',attrs={'class':'stock-bets'})
name = stockInfo.find_all(attrs={'class':'bets-name'})[0]
infoDict.update({'股票名称': 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(fpath, 'a', encoding='utf-8') as f:
f.write( str(infoDict) + '\n' )
except:
traceback.print_exc()
continue
def main():
stock_list_url = 'http://quote.eastmoney.com/stocklist.html'
stock_info_url = 'https://gupiao.baidu.com/stock/'
output_file = 'D://BaiduStockInfo.txt'
slist=[]
getStockList(slist, stock_list_url)
getStockInfo(slist, stock_info_url, output_file)
main()
实验之后,得不出任何结果,考虑到有可能是网站的缘故,故在main函数中的url用以下代码替换之后
stock_list_url = 'http://app.finance.ifeng.com/list/stock.php?t=ha'
stock_info_url = 'https://www.laohu8.com/stock/'
得出有效结果
代码优化
1.节省时间
由于已经知道获取有效数字的网站的编码是utf-8,所以直接赋值,节省了对于r.apparent_encoding的计算时间
同理对于股票具体网站的编码是’GB2312’,故直接使用,而不用让系统去计算最有可能编码方式
2.优化用户体验
通过添加动态更新的代码,让用户能够实时看到代码的进度。
全代码
import requests
from bs4 import BeautifulSoup
import re
import traceback
def getHTMLText(url, code='utf-8'):
try:
r = requests.get(url)
r.raise_for_status()
r.encoding = code
return r.text
except:
print('爬取失败')
def getStockList(lst, stockURL):
html = getHTMLText(stockURL, 'GB2312')
soup = BeautifulSoup(html, 'html.parser')
a = soup.find_all('a')
for i in a:
try:
href = i.attrs['href']
lst.append(re.findall(r"[s][hz]\d{6}", href)[0]) ## 匹配 a 标签中 href 属性以 s 开头,中间是 h 或 z ,最后是6位数字
except:
continue
def getStockInfo(lst, stockURL, fpath):
## 去掉列表里的重复选项--将列表转换为集合再转换为列表
lst = list(set(lst))
count = 0
for stock in lst:
url = stockURL + stock[-6:]
html = getHTMLText(url)
try:
if html == '': ## 判断是否空页面
continue
infoDict = {} ## 定义一个字典,存储股票信息
soup = BeautifulSoup(html, 'html.parser')
stockInfo = soup.find('div', attrs={'class':'stock-info'})
name = stockInfo.find_all(attrs={'class':'name'})[0]
price = stockInfo.find_all(attrs={'class': 'latest'})[0]
infoDict.update({'股票名称':name.text.split()[0], '最新行情':price.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(fpath, 'a', encoding='utf-8') as f:
f.write(str(infoDict) + '\n')
count = count + 1
## 增加动态进度显示
print('\r当前进度:{:.2f}%'.format(count*100/len(lst)), end='')
except:
traceback.print_exc() ## 获得发生异常的错误信息
continue
def main():
stock_list_url = 'http://app.finance.ifeng.com/list/stock.php?t=ha'
stock_info_url = 'https://www.laohu8.com/stock/'
output_file = 'D:\\StockInfo.txt'
slist = []
getStockList(slist, stock_list_url)
getStockInfo(slist, stock_info_url, output_file)
main()
需使用cmd命令行窗口运行,或者在vs中,因为 \r 在IDLE中无法刷新