return None
这个函数从字符串 s 中去匹配一个 t,例如 match(“td”,s)是在 s 中匹配一个
,它
返回 | 的开始位置与结束位置,无能这个 | 中包含什么属性。
函数先使用语句:
m=re.search(r"<"+t,s)
匹配””:
m=re.search(r">",s[a:])
那么 b=a+m.end()就是这个" | "的结束位置,无能 | 中有什么属性。通过
match(“td”,s)与 match(“/td”,s)就可以找一对......了。
例如:
import re
def match(t,s):
m=re.search(r"<"+t,s)
if m:
a=m.start()
m=re.search(r">",s[a:])
if m:
b=a+m.end()
return {"start":a,"end":b}
return None
html='''
美元 |
100 |
人民币 |
686.94 |
686.94 |
684.00 |
678.38 |
13:40:36 |
'''
while True:
m=match("td",html)
n=match("/td",html)
if m and n:
u=m["end"]
v=n["start"]
s=html[u:v].strip("").strip("\n")
print(s)
html=html[n["end"]:]
程序结果:
美元
100
4
人民币
686.94
686.94
684.00
678.38
13:40:36
结果表明 match 函数能很好地匹配
......,无论中包含什么属性。
三、设计存储数据库
设计一个 Sqlite3 数据库 rates.db,它有一张 rates 表,结构如表 1 所示。
字段名称
Currency
TSP
CSP
TBP
CBP
Time
说明
类型
varchar(256) 外汇名称(关键字)
float
现汇卖出价
现钞卖出价
现汇买入价
现钞买入价
float
float
float
varchar(256) 时间
四、编写爬虫程序
表 1 rates 表结构
爬虫程序采用两层循环,外层循环匹配 | ......
一行,内层循环匹配......
一个数据,爬虫程序如下:
import urllib.request
import re
import sqlite3
class MySpider:
def openDB(self):
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):
5
try:
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):
m = re.search(r"<" + t, s)
if m:
a = m.start()
m = re.search(r">", s[a:])
if m:
b = a + m.end()
return {"start": a, "end": b}
return None
def spider(self,url):
try:
resp = urllib.request.urlopen(url)
data = resp.read()
html = data.decode()
m = re.search(r'
', html)
html = html[m.end():]
m = re.search(r'
', html)
# 取出
...
部分
html = html[:m.start()]
i=0
while True:
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]
6
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:
# 匹配不到
... | ,退出内层循环
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:
# 匹配不到
...
,退出外层循环
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()
程序的主要函数是 spider 函数,开始时获取网站的 html 代码,然后使用:
m=re.search(r'
',html)
html=html[m.end():]
m=re.search(r'
',html)
#取出
...
部分
7
html=html[:m.start()]
匹配到
...
,取出它们中间的部分,这部分字符串包含一个表
格,表格中有很多
......
的行,使用外层循环匹配
......
对:
p = match("tr", html)
q = match("/tr", html)
a=p["end"]
b=q["start"]
tds=html[a:b]
再取出
......
的中间部分得到 tds,再使用内层循环去匹配每个
......对:
m = match("td", tds)
n = match("/td", tds)
取出 tds[m[“end”]:n[“start”]]部分就是一个数据。
五、执行爬虫程序
执行这个爬虫程序,爬取网站的外汇数据存储到数据库中,通过 show 函数显示结果如
Currency
港币
新西兰元
澳大利亚元
美元
欧元
加拿大元
英镑
日元
新加坡元
瑞士法郎
TSP
86.60
458.80
487.86
680.27
773.51
512.62
875.74
6.20
500.93
683.55
CSP
86.60
458.80
487.86
680.27
773.51
512.62
875.74
6.20
500.93
683.55
TBP
86.26
455.14
483.98
676.00
767.35
508.54
868.76
6.15
496.93
678.11
CBP
85.65
440.75
468.67
670.44
743.08
492.45
841.29
5.96
481.22
656.66
Time
15:36:30
15:36:30
15:36:30
15:36:30
15:36:30
15:36:30
15:36:30
15:36:30
15:36:30
15:36:30
下:
8