名人名言:人生用物,各有天限;夏涝太多,必有秋旱。——(元)许名奎

  额,早睡还不克不及夙兴,周六都要补课、、、


  上一篇用BS解析好界面元素之后,将我们须要的信息放到一个info的list里面给返回来出来,便利时代,info包含这些器材



#        """ return 12 infos 
# 1.title 2.limit des 3.problem des 4.input 5.output
# 6.sample input 7.sample output 8.hint 9.author
# 10.source 11.recommend 12.imgages
# the last element is a list of images """

  info的最后一个元素是一个图片的list。


  如今那,有了这些个信息,就须要把他们存到数据库里了。额,想了一下,图片的地址就不存来,直接把图片下载下来,然后经由过程html来引用就好了。所以,须要记录info里面的前11条信息,以及1个题号。


  先上代码(须要导入的器材忘了粘了 sqlalchemy import *         sqlalchemy.orm import * ):



 1 def store(start, end, url=""http://acm.hdu.edu.cn/showproblem.php?pid=""):
2 engine = create_engine("mysql://root:duoduo@localhost:3306/test?charset=utf8", encoding="utf-8", echo=True)
3 metadata = MetaData()
4 hdoj_table = Table(""hdoj"", metadata,
5 Column(""problem_id"", Integer, primary_key=True),
6 Column(""title"", String(255), nullable=False),
7 Column(""limit_description"", String(255), nullable=False),
8 Column(""problem_description"", Text, nullable=False),
9 Column(""input"", Text, nullable=False),
10 Column(""output"", Text, nullable=False),
11 Column(""sample_input"", Text, nullable=False),
12 Column(""sample_output"", Text, nullable=False),
13 Column(""hint"", Text, nullable=True),
14 Column(""author"", String(40), nullable=True),
15 Column(""source"", Text, nullable=True),
16 Column(""recommend"", String(255), nullable=True),
17 )
18
19 class Hdoj(object):
20 def __init__(self, problem_id, title, limit_description, problem_description, input, output, sample_input, sample_output, hint, author, source, recommend):
21 self.problem_id = problem_id
22 self.title = title
23 self.limit_description = limit_description
24 self.problem_description = problem_description
25 self.input = input
26 self.output = output
27 self.sample_input = sample_input
28 self.sample_output = sample_output
29 self.hint = hint
30 self.author = author
31 self.source = source
32 self.recommend = recommend
33
34 def __repr__(self):
35 return "<Hdoj(""%s"")>" % (self, title)
36
37 metadata.create_all(engine)
38
39 mapper(Hdoj, hdoj_table)
40
41 Session = sessionmaker(autoflush=True, bind=engine)
42
43 session = Session()
44
45 data = []
46 images = []
47 for i in range(start, end):
48 problem_id = str(i)
49 info = catch(url + problem_id)
50 if info[2] == ""None"":
51 continue
52 data.append(Hdoj(problem_id, info[0], info[1], info[2], info[3], info[4], info[5], info[6], info[7], info[8], info[9], info[10]))
53 images.append(info[-1])
54
55
56 length = len(data)
57 for i in range(length):
58 try:
59 session.add(data[i])
60 session.flush()
61 print ""adding""
62 except Exception as e:
63 print ""exception""
64 print e
65 session.rollback()
66 pass
67 return images


  申明:


 1 def store(start, end, url=""http://acm.hdu.edu.cn/showproblem.php?pid=""):

    start和end是开端到停止的题号,例如我想把1000~2000题都给存下来,那么就store(1000,2000)就好了,url就是之前解析过的默认题今朝缀。


2 engine = create_engine("mysql://root:123@localhost:3306/test?charset=utf8", encoding="utf-8", echo=True)

    sqlalchemy里面的,sqlalchemy那就像是一个抽象出来的数据库基类一样的器材,你只须要建树一个数据库的引擎,然后就可以在这个数据库上操纵,具体的数据库的一些建表插入操纵都不消你来费神了,很是便利。例如,我这个引擎是mysql的,用户名为root,暗码123,字符集utf8,echo是为了显示一下sqlalchemy到底干了什么,所以设定为True,当然正式公布的时辰须要改成False。


 1     metadata = MetaData()
2 hdoj_table = Table(""hdoj"", metadata,
3 Column(""problem_id"", Integer, primary_key=True),
4 Column(""title"", String(255), nullable=False),
5 Column(""limit_description"", String(255), nullable=False),
6 Column(""problem_description"", Text, nullable=False),
7 Column(""input"", Text, nullable=False),
8 Column(""output"", Text, nullable=False),
9 Column(""sample_input"", Text, nullable=False),
10 Column(""sample_output"", Text, nullable=False),
11 Column(""hint"", Text, nullable=True),
12 Column(""author"", String(40), nullable=True),
13 Column(""source"", Text, nullable=True),
14 Column(""recommend"", String(255), nullable=True),
15 )


  metadata是神马我不是很懂得,(元数据??),总之先记下来用着,然后就是新建一个表,每个oj一张表,所以,就有了上方这2~15行,单词描述的斗劲明显,不说了然就。



 1 class Hdoj(object):
2 def __init__(self, problem_id, title, limit_description, problem_description, input, output, sample_input, sample_output, hint, author, source, recommend):
3 self.problem_id = problem_id
4 self.title = title
5 self.limit_description = limit_description
6 self.problem_description = problem_description
7 self.input = input
8 self.output = output
9 self.sample_input = sample_input
10 self.sample_output = sample_output
11 self.hint = hint
12 self.author = author
13 self.source = source
14 self.recommend = recommend
15
16 def __repr__(self):
17 return "<Hdoj(""%s"")>" % (self, title)
18
19 metadata.create_all(engine)
20
21 mapper(Hdoj, hdoj_table)

  接下来新建一个Hdoj的类,并且讲这个类与方才建的数据表做好映射。


  1~14行就是Hdoj了


  19、20行里面,是sqlalchemy的器材了,19行是真正的建树引擎,20行是将类与的数据库的表做映射。


  接下来是存储:



 1     Session = sessionmaker(autoflush=True, bind=engine)
2
3 session = Session()
4
5 data = []
6 images = []
7 for i in range(start, end):
8 problem_id = str(i)
9 info = catch(url + problem_id)
10 if info[2] == ""None"":
11 continue
12 data.append(Hdoj(problem_id, info[0], info[1], info[2], info[3], info[4], info[5], info[6], info[7], info[8], info[9], info[10]))
13 images.append(info[-1])
14
15
16 length = len(data)
17 for i in range(length):
18 try:
19 session.add(data[i])
20 session.flush()
21 print ""adding""
22 except Exception as e:
23 print ""exception""
24 print e
25 session.rollback()
26 pass
27 return images


  session这个器材,小我的懂得就是一次链接,在这儿一个session就是python和数据库的一次链接,然后我们对 这个session进行一系列操纵,存储啊添加啊神马的,重视,只要session没有flush(),操纵都是在缓存里面进行的,查文档发明 commit()是提交的一个函数,它里面是会调用flush()的。


 1     Session = sessionmaker(autoflush=True, bind=engine)  
  用sessionmaker建树一个Session,绑定了之前建树的引擎。
3 session = Session()   

  建树一个Session(你用sessionmaker建树的特别的一个链接)的对象。

  5~13都是添加对象


 8         problem_id = str(i)  
9 info = catch(url + problem_id)

  用之前写好的catch函数抓取须要的信息,存到info里面,重视url变了,如许来进行题目标遍历。

10         if info[2] == ""None"":
11 continue

  这两行是防止神马的,防止数据库参加没有的题目,比如杭电的题目就到4186,若是store(10000,10010),会把着些没有的url给存到数据库里面,这不是我们想要的,若是没有这个题目标话,让他默默的失败,进行下一个链接。

 


 5     data = []
6 images = [] 

12         data.append(Hdoj(problem_id, info[0], info[1], info[2], info[3], info[4], info[5], info[6], info[7], info[8], info[9], info[10]))
13 images.append(info[-1])

  data是我真正想存到数据库里面的信息,images则是不想存到里面的图片信息,分隔分隔。



 1     length = len(data)
2 for i in range(length):
3 try:
4 session.add(data[i])
5 session.flush()
6 print ""adding""
7 except Exception as e:
8 print ""exception""
9 print e
10 session.rollback()
11 pass
12 return images


  这几行是最首要,这是真正把数据放到数据库里的。


  起首要申明为什马要用异常,我的主键用的是题号啊,第一次store(1000,1120)的时辰一般是不会错的,若是第二次我想 store(1100,1200),数据库会告诉我主键反复,不克不及添加,额,这个当时纠结了好久,各类查,无果,学长告诉我说你可以抓异常啊,弱弱的 说一句,我这还真是第一次用异常,没想到介么好用、、


  然后是rollback(),rollback像他的名字一样,回滚。session在进行一次链接的时辰,每条数据和数据库链接在一 路,直到比及rollback它才进行下一条数据的链接(这都是我本身感触感染的,若是不合错误啊话@我下下,进修中),额、怎么说那,举个例子吧,若是 说我存store(1055,1070),在1056题,4行添加数据,5行想要更新缓存,写入数据库的时辰呈现异常了,假设没有rollback这个函 数,仅仅是pass的话,session着个叫做链接的器材依然把python和数据库里面的1056进行链接,而不会向下走,成果就是下面的14条数据 持续异常,并且给的异常都是第1056题目标主键反复,就是说在轮回持续后,数据库并没有断开和1056题的链接,依然测验测验把1056题的数据加进来。(这些是真的啊,就不归去实验截图了,一会儿还要上课)


  信息要一条一条的存,包不准那一条就会有异常。固然说session有个addAll()函数,然则若是里面有一条数据出了异常,若是用我第10行的处理惩罚机制,那么那一条异常数据后面的所稀有据全部都不克不及添加了。


  因为不想把图片存到数据库里面,把它直接return出去了,新写一个函数把图片存到本地。


  就是用python处理惩罚文件的那一套,代码:



 1 def download_img(url, default_url_head=""http://acm.hdu.edu.cn/data/images/"", default_file_head=""/home/duoduo/images/"", pro_file_head=""hdoj""):
2 filename = url.split(""/"")[-1]
3 url_head = default_url_head
4 file_head = default_file_head
5
6 url_path = url_head + filename
7 print url_path
8 file_path = file_head + pro_file_head + ""/"" + filename
9 print file_path
10 try:
11 open_img = urllib2.urlopen(url_path)
12 img = open_img.read()
13 img_file = open(file_path, ""wb"")
14 img_file.write(img)
15 img_file.close()
16 print ""downloading images :"" + url_path
17 except:
18 print ""HTTP Error 404: Not Found""
19 pass

  第2~9行就是把url和本地的路径进行一些处理惩罚


  10~19行下载,依然要抓异常,因为有些图本身就挂了,打不开,会弹出404异常


  13~15就是文件的读写操纵,把图片信息存起来来。
  


  存储就到这里了,然后包一下,做一个start函数,把上方的器材都给装进来:



 1 def start(begin, end):
2 if(end < begin):
3 print ""输入有误,请搜检您的输入。""
4 return None
5
6 default_group_num = 50
7 groups = (end - begin) / default_group_num
8
9 for i in range(groups):
10 group_start = i * default_group_num + begin
11 group_end = (i + 1) * default_group_num + begin
12 images_list = store(group_start, group_end)
13 len_img_list = len(images_list)
14 for i in range(len_img_list):
15 len_img = len(images_list[i])
16 for j in range(len_img):
17 download_img(images_list[i][j])
18
19 if (end - begin) >= 0 :
20 last_group_start = groups * default_group_num + begin
21 images_list = store(last_group_start, end + 1)
22 len_img_list = len(images_list)
23 for i in range(len_img_list):
24 len_img = len(images_list[i])
25 for j in range(len_img):
26 download_img(images_list[i][j])

 6     default_group_num = 50

  默认一次存几许数据,我怕一次存太多,内存受不了,或者是等了10来分钟成果半途崩了,还要从头来,麻烦。
7 groups = (end - begin) / default_group_num

  groups以及一下的for轮回就是做分组处理惩罚的。

  python抓数据,存数据就彻底ok了,下一步就是用django显示看看是否正确,django的静态文件此次是深切领会了,上课去先,晚上或者明天在写下一篇吧。  




人生用物,各有天限;夏涝太多,必有秋旱。——(元)许名奎

posted on 2014-10-08 23:31  yuyezhulan  阅读(175)  评论(0编辑  收藏  举报