手把手教你入门Python爬虫
前言
在上一篇文章中,我们讲解到了基础的计算机网络知识,并完成了“爬取豆瓣Top250电影信息”的项目。那么这一次,作者将带领大家完成“爬取中国银行外汇牌价”项目。
1. 观察网站,寻找规律
我们首先登录中国银行外汇牌价网站: https://www.boc.cn/sourcedb/whpj/index.html
可以看出,我们今天要爬取的网站,在页面设计上大体分为三大块:顶部的功能区、中部的外汇牌价数据和底部的描述信息。
我们切换到第二页,网站显示出如下内容:
通过对比这两页的内容(读者可自行翻阅后续页码),我们发现,该网站有关外汇牌价的页面,每一个页面都是按照固定的国家顺序、列属性顺序显示外汇牌价,页与页间的不同点是外汇牌价刷新的时间不同。
因此,本项目设定任务目标为爬取中国银行外汇牌价网站的第一页所有外汇牌价信息。
2. 项目架构构思
在各函数功能的设计上,我们依然借鉴手把手教你Python爬虫(一)中的设计思路。
# 加载包
import bs4 # 网页解析,获得数据
import re # 正则表达式,进行文字匹配
import urllib.request,urllib.error # 指定URL,获取网页数据
import xlwt # 进行excel操作
from bs4 import BeautifulSoup # 网页解析,获得数据
# 定义主函数
def main():
# 定义askURL(url)用于得到指定URL的html文件
def askURL(url):
# 定义getData()用于解析网页,获取数据
def getData():
# 定义saveData()用于保存数据
def saveData(currencydata,savepath):
# 定义程序执行入口
if __name__ == "__main__":
3. 程序编写
- 编写(部分)主函数
def main():
# 定义网址URL
baseurl = 'https://www.boc.cn/sourcedb/whpj/index.html'
- 编写askURL(url)函数
def askURL(url):
# 模拟浏览器头部信息
head = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.105 Safari/537.36'
}
# 封装消息,发送请求
request = urllib.request.Request(url, headers=head)
html = ''
try:
# response变量用于接受返回html文件
response = urllib.request.urlopen(request)
html = response.read().decode('utf-8')
except urllib.error.URLError as e:
if hasattr(e, 'code'):
print(e.code)
if hasattr(e, 'reason'):
print(e.reason)
return html
- 编写getData()函数
def getData(url):
# 用于后续保存外汇牌价数据
datalist = []
# 保存获取到的网页源码
html = askURL(url)
# 解析爬取的网页
soup = BeautifulSoup(html, 'html.parser')
# 如果在此处执行print(soup)即打印查看经过BeautifulSoup()方法解析到的网页
# 可以发现我们需要的外汇牌价信息,被许多无用超文本标记语言包裹
# 可以发现,所需的外汇牌价信息都有一个特点,即被<tr>标签包裹
# 因此决定筛选出所有<tr>标签,并将筛选出的结果保存到列表中
item = soup.find_all('tr')
# 读者可以在此处执行print(item)查看item列表中具体有哪些内容
# 发现item中,从第三个标签开始是货币内容
# 决定编写循环,对item中的第3个至第30个对象进行遍历
# 没遍历一个对象,就从中利用正则表达式提取出有用信息,存入datalist[]
for i in range(2,29): # 查找符合要求的字符串(td标签),形成列表
data = [] # 保存一种货币的所有信息
currentitem = item[i] # 第i个tr标签
currentitem = str(currentitem) # 将标签及其内容转化为字符串格式,方便正则表达式比对
# 正则表达式currencyRules在下文编写
findcurrency = re.findall(currencyRules, currentitem) # 正则表达式比对
datalist.append(findcurrency)
return datalist
- 编写正则表达式,并定义为全局变量
currencyRules = re.compile(r'<td>(.*)</td>')
以日元为例,经过BeautifulSoup()方法解析过后的源码为:
<tr>
<td>日元</td>
<td>6.564</td>
<td>6.36</td>
<td>6.6123</td>
<td>6.6225</td>
<td>6.6118</td>
<td class="pjrq">2020-08-03</td>
<td>19:06:34</td>
</tr>
因此我们要做的,就是编写一个正则表达式,识别<tr> … </tr>标签(此时已经被str()方法转换为字符串)内的:以<td>开头,中间包含零个或多个任意字符,以</td>结尾的字符串。具体代码如上。
注意,该正则表达式不能识别出:
<td class="pjrq">2020-08-03</td>
鉴于本例只用于爬取一天的信息,故该信息可以省略。
- 编写部分主函数(续)
def main():
# 定义网址URL
baseurl = 'https://www.boc.cn/sourcedb/whpj/index.html'
# 获取外汇牌价数据
currencydata = getData(baseurl)
- 编写保存数据saveData()函数
def saveData(currencydata,savepath): # 参数为:待保存数据,保存路径
# 创建一个excel文件
book = xlwt.Workbook(encoding='utf-8',style_compression=0)
# 创建一个sheet表
sheet = book.add_sheet('中国银行外汇牌价', cell_overwrite_ok=True)
# 定义一个元组,元素为列属性名称
col = ('货币名称','现汇买入价','现钞买入价','现汇卖出价','现钞卖出价','中行折算价','发布时间')
# 写入列名
for i in range(0,7):
sheet.write(0,i,col[i])
# 写入数据
for i in range(0,27):
h = i +1
print('正在写入第 %d 条' % h)
data_1 = currencydata[i]
for j in range(0,7):
sheet.write(i + 1,j,data_1[j])
book.save(savepath)
- 编写完整主函数以及程序入口
def main():
# 定义网址URL
baseurl = 'https://www.boc.cn/sourcedb/whpj/index.html'
# 获取外汇牌价数据
currencydata = getData(baseurl)
savepath = '中国银行外汇牌价.xls'
saveData(currencydata, savepath) # 定义将数据保存到当前文件夹下
if __name__ == "__main__":
print('开始执行爬虫程序')
main()
print('爬取完毕')
4. 爬取结果
到这里,即完成了对中国银行外汇牌价数据的爬取。