如下是我写的代码,但是始终无法成功提取外汇实时利率信息,就是提取不到内容
import urllib.request
import re
import sqlite3
class MySpider:
def openDB(self):
初始化数据库,创建数据库 rates.db 与一张空表 rates
self.con = sqlite3.connect("rates.db")## 创建/连接数据库文件
self.cursor = self.con.cursor()# 获取数据库游标
try:
self.cursor.execute("drop table rates")
except:
pass
sql = "create table rates (Currency varchar(256) primary key, TSP float, CSP float, TBP float, CBP float, Time varchar(256))"
self.cursor.execute(sql)
def closeDB(self):
# 关闭数据库
self.con.commit()
self.con.close()
def insertDB(self, Currency, TSP, CSP, TBP, CBP, Time):
# 将记录插入数据库
try:
# 参数化查询防止SQL注入
sql = "insert into rates (Currency, TSP, CSP, TBP, CBP, Time) values (?,?,?,?,?,?)"
self.cursor.execute(sql, [Currency, TSP, CSP, TBP, CBP, Time])
except Exception as err:
print(err)
def show(self):
# 显示函数
self.cursor.execute("select Currency, TSP, CSP, TBP, CBP, Time from rates")
rows = self.cursor.fetchall()
# 打印表头
print("%-18s%-12s%-12s%-12s%-12s%-12s" % ("Currency", "TSP", "CSP", "TBP", "CBP", "Time"))
# 打印数据行
for row in rows:
print("%-18s%-12.2f%-12.2f%-12.2f%-12.2f%-12s" % (row[0], row[1], row[2], row[3], row[4], row[5]))
def match(self, t, s):
# 匹配函数
# 查找标签开始位置 (带<) s表示待匹配的HTML字符串
'''
作用:匹配以 < 开头的标签,例如:
当t = "tr"
时,匹配 < tr(包括 < tr class ="rate" > )
当t = "/tr"
时,匹配 < / tr(闭合标签)
r"<" + t 动态拼接标签,支持带斜杠的闭合标签
不匹配完整标签(如不包含 >),因为后续需要单独匹配 > 的位置
'''
m = re.search(r"<" + t, s)
if m:# 检查m是否为真,即是否找到了匹配的标签开始位置。
a = m.start() # 记录标签起始字符<的位置,若 HTML 为<tr class="rate">,则m.start()返回 0(< 的位置)
'''
作用:定位标签的闭合符号 >,例如:
对于<tr class="rate">,在s[a:](即 "tr class="rate">")中找到 > 的位置
匹配成功后,m.end()返回相对位置(如在子串中的第 12 位)
'''
m = re.search(r">", s[a:])# 从a位置开始找>的位置
if m:
b = a + m.end()# 计算标签整体结束位置(包括>) 假设 <在位置 0,> 在位置 12(相对于原字符串),则b=0+12=12
return {"start": a, "end": b} # 返回标签的起止位置
return None # 匹配失败返回None
def spider(self, url):
# 爬虫函数
try:
resp = urllib.request.urlopen(url) # 发送HTTP请求
data = resp.read() # 获取响应内容
html = data.decode()# 解码为字符串
# 查找汇率数据容器
m = re.search(r'<tbody>', html)
#if m:
html = html[m.end():] # 截取容器之后的内容
m = re.search(r'</tbody>', html)# 查找容器结束位置
#if m:
# 取出 <table">…</table> 部分
html = html[:m.start()]# 截取容器内的内容
i = 0
while True:
# 查找<tr>标签
p = self.match("tr", html)
q = self.match("/tr", html)
if p and q:
i = i + 1
a = p["end"]
b = q["start"]
tds = html[a:b]# 提取该行内容
row = []
count = 0
while True:
m = self.match("td", tds)
n = self.match("/td", tds)
if m and n:
u = m["end"]
v = n["start"]
count += 1
if count <= 8:
row.append(tds[u:v].strip())
tds = tds[n["end"]:]
else:
# 匹配不到 <td …>…</td>,退出内层循环
break
if i >= 2 and len(row) == 8:
Currency = row[0]
TSP = float(row[3])
CSP = float(row[4])
TBP = float(row[5])
CBP = float(row[6])
Time = row[7]
self.insertDB(Currency, TSP, CSP, TBP, CBP, Time)
html = html[q["end"]:]
else:
# 匹配不到 <tr>…</tr>,退出外层循环
break
except Exception as err:
print(err)
def process(self):
# 爬取过程函数
self.openDB()
self.spider("http://fx.cmbchina.com/hq/")
self.show()
self.closeDB()
主程序
spider = MySpider()
spider.process()