1.当获取https链接是需要添加参数 validate_cert=False

 

 

2.增加翻页操作

1     @config(age=10 * 24 * 60 * 60)
2     def index_page(self, response):
3         for each in response.doc('#thumbnail * > h2 > a').items():
4             self.crawl(each.attr.href,validate_cert=False, callback=self.detail_page)
5         next = response.doc('.next')
6         self.crawl(next.attr.href,validate_cert=False,callback=self.index_page)

 

 

3.自定义工具类 参考https://vel.life/Pyspider%E6%93%8D%E4%BD%9C%E6%8C%87%E5%8D%97/

  1 #!/usr/bin/env python
  2 # -*- encoding: utf-8 -*-
  3 # Created on 2017-12-05 20:59:56
  4 # Project: boeing
  5 
  6 from pyspider.libs.base_handler import *
  7 import re
  8 from pyspider.database.mysql.mysqldb import SQL
  9 import sys  
 10 import os
 11 import time as ti
 12 from dateutil import parser
 13   
 14 reload(sys)  
 15 sys.setdefaultencoding('utf8')
 16 
 17 #图片存放目录
 18 DIR_PATH = "./"
 19 
 20 class Handler(BaseHandler):
 21     
 22     headers= {
 23     "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
 24     "Accept-Encoding":"gzip, deflate, sdch",
 25     "Accept-Language":"zh-CN,zh;q=0.8",
 26     "Cache-Control":"max-age=0",
 27     "Connection":"keep-alive",
 28     "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
 29     }
 30 
 31     crawl_config = {
 32         'itag': 'v1.1',
 33         "headers" : headers,
 34         "timeout" : 100000
 35     }
 36     
 37     def __init__(self):
 38         self.dir_path = DIR_PATH
 39         self.tool = Tool()
 40     
 41     @every(minutes=24 * 60)
 42     def on_start(self):
 43         self.crawl('http://boeing.mediaroom.com/news-releases-statements', callback=self.index_page)
 44 
 45     @config(age=10 * 24 * 60 * 60)
 46     def index_page(self, response):
 47         for each in response.doc('.archive_nav > a').items():
 48             year=each.text()
 49             if(year != "Search"):
 50                 if(year=="2016" or year=="2015"):
 51                     self.crawl(each.attr.href, callback=self.news_page)
 52                 
 53     def news_page(self, response):
 54         for each in response.doc('.item').items():
 55             time=each.find('div').eq(0).text()
 56             datetime_struct = parser.parse(time)
 57             time=datetime_struct.strftime('%Y-%m-%d')
 58             self.crawl(each.find('div').find('a').attr.href, save={'time': time},callback=self.news,connect_timeout = 5000, timeout = 20000)
 59         for each_page in response.doc('.table_footer > b > a').items():
 60             self.crawl(each_page.attr.href, callback=self.news_page2)
 61             
 62     def news_page2(self, response):
 63         for each in response.doc('.item').items():
 64             time=each.find('div').eq(0).text()
 65             datetime_struct = parser.parse(time)
 66             time=datetime_struct.strftime('%Y-%m-%d')
 67             self.crawl(each.find('div').find('a').attr.href, save={'time': time},callback=self.news,connect_timeout = 5000, timeout = 20000)
 68         
 69     def news(self, response):
 70         time=response.save['time']
 71         if response.doc('#assets_20295_130083-117_tab_link'):
 72             self.crawl(response.doc('#assets_20295_130083-117_tab_link').attr.href,save={'time': time}, callback=self.detail_page,validate_cert=False,connect_timeout = 5000, timeout = 20000)
 73         else:
 74             self.crawl(response.url, save={'time': time},callback=self.detail_page,validate_cert=False,connect_timeout = 5000, timeout = 20000)
 75         
 76     @config(priority=2)
 77     def detail_page(self, response):
 78         title=response.doc('.wd_news_releases-detail > h1').text()
 79         time=response.save['time']
 80         content = ''
 81         for each in response.doc('.news_body > p').items():
 82             content += each.text()
 83         url = response.url
 84         picture_url = ''
 85         picture_local_path = ''
 86         file_title = re.sub('[\/:*?"<>|]','-',title)
 87         imgDir = self.dir_path
 88         for imgElem in response.doc('.detail_image > img').items():
 89             imgUrl = imgElem.attr.src
 90             picture_url += imgUrl + ';'
 91             if imgUrl:
 92                 #获取图片文件后缀
 93                 extension = self.tool.get_extension(imgUrl)
 94                 name = self.tool.get_name(imgUrl)
 95                 #拼接图片名
 96                 file_name = name + "." + extension
 97                 picture_local_path += ';' + file_name
 98                 self.crawl(imgUrl,callback=self.save_img,save={"file_name":file_name, "imgDir":imgDir},validate_cert=False, connect_timeout = 5000, timeout = 20000)
 99                 
100         for imgElem in response.doc('.PRN_ImbeddedAssetReference > p > img').items():
101             imgUrl = imgElem.attr.src
102             picture_url += imgUrl + ';'
103             if imgUrl:
104                 #获取图片文件后缀
105                 extension = self.tool.get_extension(imgUrl)
106                 name = self.tool.get_name(imgUrl)
107                 #拼接图片名
108                 file_name = name + "." + extension
109                 picture_local_path += ';' + file_name
110                 self.crawl(imgUrl,callback=self.save_img,save={"file_name":file_name, "imgDir":imgDir},validate_cert=False, connect_timeout = 5000, timeout = 30000)   
111                 
112         return {
113             "title":title,
114             "introduction":"null",
115             "time":time,
116             "content":content,
117             "keywords":"null",
118             "name":"boeing",
119             "source":"原创",
120             "url":url,
121             "picture_url":picture_url,
122             "picture_local_path":picture_local_path
123         }
124     
125     #保存图片
126     def save_img(self,response):
127         content = response.content
128         file_name = response.save["file_name"]
129         imgDir = response.save["imgDir"]
130         file_path = imgDir + file_name
131         self.tool.save_img(content,imgDir,file_path)
132     
133     def on_result(self,result):
134         if not result or not result['title']:
135             return
136         sql = SQL()
137         sql.insert('boeing',**result)
138         
139 #工具类    
140 class Tool:
141     #保存图片
142     def save_img(self,content,imgDir,path):
143         if not os.path.exists(imgDir):                         
144             os.makedirs(imgDir)
145         f = open(path,"wb" )
146         f.write(content)
147         f.close()
148 
149     #获取url后缀名
150     def get_extension(self,url):                            
151         extension = url.split(".")[-1]
152         return extension 
153     
154     #获取图片名
155     def get_name(self,url):
156         name=url.split("/")[-1].split(".")[0]
157         return name

 

  

4.

  1 #爬取模板:加注释版
  2 #!/usr/bin/env python
  3 # -*- encoding: utf-8 -*-
  4 # Created on 2017-12-05 20:59:56
  5 # Project: boeing
  6 
  7 from pyspider.libs.base_handler import *
  8 import re
  9 from pyspider.database.mysql.mysqldb import SQL
 10 import sys  
 11 import os
 12 import time as ti
 13 from dateutil import parser
 14   
 15 reload(sys)  
 16 sys.setdefaultencoding('utf8')
 17 
 18 #图片存放目录
 19 DIR_PATH = "./"  # pyspider默认目录?
 20 
 21 class Handler(BaseHandler):
 22     
 23     headers= {
 24     "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
 25     "Accept-Encoding":"gzip, deflate, sdch",
 26     "Accept-Language":"zh-CN,zh;q=0.8",
 27     "Cache-Control":"max-age=0",
 28     "Connection":"keep-alive",
 29     "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
 30     }
 31 
 32     crawl_config = {
 33         'itag': 'v1.1',
 34         "headers" : headers,
 35         "timeout" : 100000
 36     }
 37     
 38     def __init__(self):
 39         self.dir_path = DIR_PATH
 40         self.tool = Tool()
 41     
 42     @every(minutes=24 * 60)
 43     def on_start(self):                #这里设置你要爬取的网页,先登录看看是否对应,否则容易出错
 44         self.crawl('http://boeing.mediaroom.com/news-releases-statements', callback=self.index_page)
 45 
 46     @config(age=10 * 24 * 60 * 60)
 47     def index_page(self, response):                #设置索引页
 48         for each in response.doc('.archive_nav > a').items():
 49             year=each.text()
 50             if(year != "Search"):
 51                 if(year=="2016" or year=="2015"):            #这里设置爬取网页新闻的年份(按年份分类),最好把最新的年份都爬取下来【注意,不是所有的网站都有这个分类!】
 52                     self.crawl(each.attr.href, callback=self.news_page)
 53     
 54     #进入某一年份的index页面            
 55     def news_page(self, response):
 56         for each in response.doc('.item').items():
 57             time=each.find('div').eq(0).text()          # find'div'是找到.item下的所有元素,然后eq(0)获取第0个(首个)元素的text(),即内容
 58             datetime_struct = parser.parse(time)
 59             time=datetime_struct.strftime('%Y-%m-%d')   # 这里的功能是,将网页代表时间的字符串格式化为%Y-%m-%d(原网页是英文格式)
 60             self.crawl(each.find('div').find('a').attr.href, save={'time': time},callback=self.news,connect_timeout = 5000, timeout = 20000)    #调取新闻页。注意,所有的time都是提前在index页获取的,因此需要传递给最后的处理函数
 61         for each_page in response.doc('.table_footer > b > a').items():
 62             self.crawl(each_page.attr.href, callback=self.news_page2)   #调取其它新闻页
 63     
 64     #基于该年份,调取其它index页(一个年份可能对应多个index页面,一个index页面又对应多个新闻页)       
 65     def news_page2(self, response):
 66         for each in response.doc('.item').items():
 67             time=each.find('div').eq(0).text()  #同理,以下
 68             datetime_struct = parser.parse(time)
 69             time=datetime_struct.strftime('%Y-%m-%d')
 70             self.crawl(each.find('div').find('a').attr.href, save={'time': time},callback=self.news,connect_timeout = 5000, timeout = 20000)    # each.find('div').find('a').attr.href是获得新闻页的url
 71     
 72     #主方法,进入新闻页
 73     def news(self, response):
 74         time=response.save['time']  #记录已经格式化的时间,继续往下传递
 75         if response.doc('#assets_20295_130083-117_tab_link'):   # 这里的if else是用来判断新闻有无图片
 76             self.crawl(response.doc('#assets_20295_130083-117_tab_link').attr.href,save={'time': time}, callback=self.detail_page,validate_cert=False,connect_timeout = 5000, timeout = 20000)
 77         else:
 78             self.crawl(response.url, save={'time': time},callback=self.detail_page,validate_cert=False,connect_timeout = 5000, timeout = 20000)
 79         
 80     @config(priority=2)
 81     def detail_page(self, response):
 82         title=response.doc('.wd_news_releases-detail > h1').text()  #通过正则表达式获取新闻题目
 83         time=response.save['time']  #最终获取到时间
 84         content = ''    #初始化新闻内容为空,字符串
 85         for each in response.doc('.news_body > p').items():  # 对于每一个在.news_body > p中的内容都添加到content中
 86             content += each.text()
 87         url = response.url      # 保存网址为当前网址
 88         picture_url = ''    #与content同理
 89         picture_local_path = ''
 90         file_title = re.sub('[\/:*?"<>|]','-',title)    # ???某个正则表达式?
 91         imgDir = self.dir_path
 92  #处理图片的方法1:
 93         for imgElem in response.doc('.detail_image > img').items():
 94             imgUrl = imgElem.attr.src
 95             picture_url += imgUrl + ';'
 96             if imgUrl:
 97                 #获取图片文件后缀
 98                 extension = self.tool.get_extension(imgUrl)
 99                 name = self.tool.get_name(imgUrl)
100                 #拼接图片名
101                 file_name = name + "." + extension
102                 picture_local_path += ';' + file_name
103                 self.crawl(imgUrl,callback=self.save_img,save={"file_name":file_name, "imgDir":imgDir},validate_cert=False, connect_timeout = 5000, timeout = 20000)
104   #处理图片的方法2:               
105         for imgElem in response.doc('.PRN_ImbeddedAssetReference > p > img').items():
106             imgUrl = imgElem.attr.src
107             picture_url += imgUrl + ';'
108             if imgUrl:
109                 #获取图片文件后缀
110                 extension = self.tool.get_extension(imgUrl)
111                 name = self.tool.get_name(imgUrl)
112                 #拼接图片名
113                 file_name = name + "." + extension
114                 picture_local_path += ';' + file_name
115                 self.crawl(imgUrl,callback=self.save_img,save={"file_name":file_name, "imgDir":imgDir},validate_cert=False, connect_timeout = 5000, timeout = 30000)   
116                 
117         return {
118             "title":title,
119             "introduction":"null",
120             "time":time,
121             "content":content,
122             "keywords":"null",
123             "name":"boeing",      #这里根据你建的表格名修改
124             "source":"原创",
125             "url":url,
126             "picture_url":picture_url,
127             "picture_local_path":picture_local_path
128         }
129     
130     #保存图片
131     def save_img(self,response):
132         content = response.content
133         file_name = response.save["file_name"]
134         imgDir = response.save["imgDir"]
135         file_path = imgDir + file_name
136         self.tool.save_img(content,imgDir,file_path)
137     
138     def on_result(self,result):
139         if not result or not result['title']:
140             return
141         sql = SQL()
142         sql.insert('boeing',**result)       #这里也要对应修改哦
143         
144 #工具类    
145 class Tool:
146     #保存图片
147     def save_img(self,content,imgDir,path):
148         if not os.path.exists(imgDir):                         
149             os.makedirs(imgDir)
150         f = open(path,"wb" )        #写入文件
151         f.write(content)
152         f.close()
153 
154     #获取url后缀名
155     def get_extension(self,url):                            
156         extension = url.split(".")[-1]
157         return extension 
158     
159     #获取图片名
160     def get_name(self,url):
161         name=url.split("/")[-1].split(".")[0]
162         return name

 

 

5.代码:功能for_compositesworld(复合材料世界)爬虫程序_详注

  1 #!/usr/bin/env python
  2 # -*- encoding: utf-8 -*-
  3 # Created on 2018-03-18 18:13:33
  4 # Project: compositesworld
  5 #问题:
  6 #1. 爬取introduction项的正则表达式不够准确,一部分项爬不下来      ---已解决(注意分析网站的html,而不是一味地依赖CSS选择器)
  7 #2. 如何动态、高效地控制爬取的年份截止日期?比如,最早到2016.01.01
  8 #3. 在单步调试,尝试调用保存图片函数时出现 Exception: HTTP 599:…… OpenSSL SSL_connect: SSL_ERROR_SYSCALL in connection to d2n4wb9orp1vta.cloudfront.net:443  错误     ---已解决(似乎与网络连接状况有关,但正常运行时反而没什么问题。暂时忽略)
  9 #4. python反反爬虫机制(代理IP。sleep延时:防止爬取过快导致封IP)      ---已解决。 使用ti.sleep(t),t为参数,单位为秒。如:ti.time.sleep(3),表示停顿3秒后继续执行
 10 
 11 from pyspider.libs.base_handler import *        #这个库中定义了爬取的各种控制函数和方法
 12 import re   #re就是regular expression,即正则表达式。正则表达式(通项公式)是用来简洁表达一组字符串的表达式。优势是简洁,一行胜千言。这个库主要用于字符串匹配。
 13 from pyspider.database.mysql.mysqldb import SQL
 14 import sys      #用于接下来修改编码格式
 15 import os       #OS库提供了使用各种操作系统功能的接口
 16 import time as ti       # 用于延时控制
 17 from dateutil import parser       #日期处理库,parser子库是根据字符串解析成datetime
 18 
 19 #编码转换
 20 reload(sys)     #Python运行的时候首先加载了site.py,在site.py文件里有这么一段代码:
 21                 #    if hasattr(sys, "setdefaultencoding"):
 22                 #        del sys.setdefaultencoding
 23                 #可以看出,在sys加载后,setdefaultencoding方法被删除了,所以我们要通过重新导入sys来设置系统编码
 24 sys.setdefaultencoding('utf8')    #设置默认编码,UTF-8
 25 
 26 #图片存放目录
 27 DIR_PATH = "./"      # ./ 的意思是:当前目录(登录pyspider时)
 28 
 29 class Handler(BaseHandler):
 30     
 31     headers= {
 32     "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
 33     "Accept-Encoding":"gzip, deflate, sdch",
 34     "Accept-Language":"zh-CN,zh;q=0.8",
 35     "Cache-Control":"max-age=0",
 36     "Connection":"keep-alive",
 37     "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
 38     }
 39 
 40     crawl_config = {
 41         'itag': 'v1.1',        #修改这个tag号,可以重新启动爬取
 42         "headers" : headers,
 43         "timeout" : 100000
 44     }
 45     
 46     
 47     def __init__(self):
 48         self.dir_path = DIR_PATH
 49         self.tool = Tool()
 50     
 51     
 52     @every(minutes=24 * 60)            # @every修饰器,表示每24小时会执行一次
 53     def on_start(self):                # 这里设置你要爬取的网页URL(最好是列表的形式,按更新顺序排列),先登录看看是否对应,否则容易出错
 54         self.crawl('https://www.compositesworld.com/news/list',validate_cert=False, callback=self.index_page)    # self.crawl 告诉 pyspider 抓取指定页面,然后使用 callback 函数对结果进行解析,并调用接下来的index_page
 55 # 总结:
 56 # 通过 on_start 回调函数,作为爬取的入口点,当点击主面板上的 run 的时候,就是调用这个函数,启动抓取。
 57 # self.crawl 告诉调度器,我们需要抓取 'https://www.compositesworld.com/news/list' 这个页面,然后使用 callback=self.index_page 这个回调函数进行解析。
 58 # 所有 return 的内容默认会被捕获到 resultdb 中,可以直接在 WEBUI 上看到(如果结果)。
 59 
 60     
 61     @config(age=10 * 24 * 60 * 60)    #在这表示我们认为 10 天内页面有效,不会再次进行更新抓取
 62     #由此,注意,pyspider不会抓取同一个URL两次(永久丢弃),即使修改了代码,对于第一次运行该项目并修改并第二次运行该项目的初学者来说,这是非常常见的。
 63     #以上是引述。但是,在实际操作WebUI时,通过单步调试可以很方便地抓取同一个页面。
 64     def index_page(self, response):                #设置索引页
 65         for each in response.doc('.headline > a').items(): 
 66             self.crawl(each.attr.href, validate_cert=False,callback=self.detail_page)
 67         next = response.doc('a[aria-label="Next"]')
 68         self.crawl(next.attr.href,validate_cert=False, connect_timeout = 5000, timeout = 20000,callback=self.index_page)
 69         # validate_cert=False 参数,用来解决SSL证书问题,对于以“https”开头的网站,必须添加
 70     
 71     @config(priority=2)
 72     def detail_page(self, response):
 73         # 使用CSS正则表达式工具修改doc()中的路径,进行页面上的元素的采集
 74         title = response.doc('.content-headline').text()
 75         introduction = response.doc('.col-sm-12 > h1').text()
 76         time = response.doc('.cell-vert-center > div > span').text()
 77         time = time[10:] #我这里采用了截取字符段的形式,获得真正的时间字符子序列(不通用!!!)
 78         datetime_struct = parser.parse(time)
 79         time=datetime_struct.strftime('%Y-%m-%d')   # 这里的功能是,将网页代表时间的字符串格式化为%Y-%m-%d(原网页是英文格式)
 80         content = response.doc('#short > div > div > p').text()
 81         url = response.url
 82         picture_url = ''    #与content同理
 83         picture_local_path = ''
 84         file_title = re.sub('[\/:*?"<>|]','-',title)
 85         imgDir = self.dir_path
 86         for imgElem in response.doc('picture > img').items():
 87             imgUrl = imgElem.attr.src
 88             imgUrl = imgUrl[:-10]  #为了截掉后面多余的字段";width=560",总共10个字符(不通用!!!)
 89             picture_url += imgUrl + ';'
 90             if imgUrl:
 91                 #获取图片文件后缀
 92                 extension = self.tool.get_extension(imgUrl)
 93                 name = self.tool.get_name(imgUrl)
 94                 #拼接图片名
 95                 file_name = name + "." + extension
 96                 picture_local_path += ';' + file_name
 97                 self.crawl(imgUrl,callback=self.save_img,save={"file_name":file_name, "imgDir":imgDir},validate_cert=False, connect_timeout = 5000, timeout = 20000)   
 98                 # 这里回调了save_img函数,在单步调试时可以明显看到
 99 
100     # def detail_page(self, response)作为结果返回一个对象。
101     # 结果将被resultdb默认捕获。
102     # 可以通过覆盖on_result(self, result)自己管理结果的方法。        
103         return {    # 与你建立的表结构对应。这是python中的字典结构,即“键-值对”
104             "title":title,
105             "introduction":introduction,
106             "time":time,
107             "content":content,
108             "keywords":"null",
109             "name":"compositesworld",      #这里根据你建的表格名修改
110             "source":"原创",
111             "url":url,
112             "picture_url":picture_url,
113             "picture_local_path":picture_local_path
114         }
115 
116     
117     #保存图片
118     def save_img(self,response):    # 可以看到,上面save中保存的内容其实通过response传了过来
119         content = response.content  # resp.content返回的是bytes型也就是二进制的数据,resp.text返回的是Unicode型的数据。
120                                     # 简而言之,如果你想取文本,可以通过r.text。    如果想取图片,文件,则可以通过r.content。
121         file_name = response.save["file_name"]
122         imgDir = response.save["imgDir"]
123         file_path = imgDir + file_name
124         self.tool.save_img(content,imgDir,file_path)
125     
126     #数据存储函数:on_result方法
127     # 调试的时候建议将 on-result 整个移除,便于显示实时获取结果。最后再保存到数据库
128     def on_result(self,result):         
129         if not result or not result['title']:    # 如果没到最后,继续返回数据
130             return
131         sql = SQL()        # 覆盖默认方法,使用mysqldb文件中定义的方法,连接数据库
132         sql.insert('compositesworld',**result)    #将结果插入到表格。同理,这里根据你建的表格名修改    
133         
134     
135 #工具类    
136 class Tool:
137     #保存图片
138     def save_img(self,content,imgDir,path):
139         if not os.path.exists(imgDir):     # os.path.exists(name)判断是否存在文件或目录name
140             os.makedirs(imgDir)  # os.makedirs() 方法用于递归创建目录
141         f = open(path,"wb" )     # wb 以只写方式打开
142         f.write(content)        # 写入文件
143         f.close()
144 
145     #获取url后缀名
146     def get_extension(self,url):                            
147         extension = url.split(".")[-1]
148         return extension 
149     
150     #获取图片名
151     def get_name(self,url):
152         name=url.split("/")[-1].split(".")[0]
153         return name

 

 

6.封装for_jeccomposites(JEC)伪宏控制__范式编

  1 #!/usr/bin/env python
  2 # -*- encoding: utf-8 -*-
  3 # Created on 2018-03-19 22:26:12
  4 # Project: jeccomposites
  5 #问题:
  6 #1. 爬取下来的content是一连串的字符串,没有考虑到换行的问题,可能需要添加'\n'?
  7 #2. 爬取这个网站的content似乎有一段开头是单独放在title的class后面的,或许添加该段?
  8 #3. 是否应该增加一个 tag 标签属性,因为很多网站只有tag但没有keywords,或者两者认为一致?   
  9 #4. [Caution]图片存储功能出现异常错误。显示TypeError与'NoneType'和Unicode'有关   ----已解决(第一,os.makedirs的返回值不是路径。改正这个之后。第二,非常坑!一个意想不到的意外错误!!!!与空格、制表符对齐的区别有关,两者不能混用!!!)
 10 
 11 
 12 #**********************************************************************************----------~~~~~~~~\
 13 #伪宏控制__范式编程
 14 #------(理论上)你只需要在这里[正确]填入所有信息,整个程序即可运行!【只适用于单一index的爬取。多重分类页面,或者需要对采集的数据做进一步规范化,则必须在后面相应地方改进】
 15 project_name = "jeccomposites"         #你的项目 的名称
 16 website_url_initial = 'http://www.jeccomposites.com/knowledge/international-composites-news'  #你爬取的初始网页(index页) 的地址
 17 detail_page_css = '.nodetitle > a'                            #新闻页面链接     的CSS表达式
 18 next_page_css = '.pager-next > a'                            #下一页链接     的CSS表达式
 19 title_css = '.content > h1'                                    #新闻标题        的CSS表达式
 20 introduction_css = '.content-block-txt > p'                    #新闻简介        的CSS表达式
 21 time_css = '.content-block-txt > div'                        #发布时间        的CSS表达式
 22 content_css = '.block-system > div > div div > div > p'        #新闻内容        的CSS表达式
 23 img_css = '.content > a > img'                                #新闻图片        的CSS表达式
 24 keywords_css = 'null'                                        #关键词,一般页面中无,因此默认为空。#!【重要:如果其他的 *_css 在网页中也找不到对应项的话,可以填'null',程序将自动返回空值】
 25 source_declaration = "原创"                                    #原创声明,一般不改动
 26 #**********************************************************************************-----------~~~~~~~/
 27 
 28 from pyspider.libs.base_handler import *        #这个库中定义了爬取的各种控制函数和方法
 29 import re   #re就是regular expression,即正则表达式。正则表达式(通项公式)是用来简洁表达一组字符串的表达式。优势是简洁,一行胜千言。这个库主要用于字符串匹配。
 30 from pyspider.database.mysql.mysqldb import SQL
 31 from pyspider.database.mysql.mysqldb_new import SQL as SQL_new
 32 import sys      #用于接下来修改编码格式
 33 import os       #OS库提供了使用各种操作系统功能的接口
 34 import time as ti       # 用于延时控制
 35 from dateutil import parser       #日期处理库,parser子库是根据字符串解析成datetime
 36 
 37 #根据项目名称,自动创建表
 38 sql_new = SQL_new()
 39 sql_new.create_table(project_name)
 40 
 41 
 42 #图片存放目录【在当前目录自动创建项目子目录,分类各项目的爬取内容。可实现多项目的同时爬取,而内容分开】
 43 path_for_project = "./"+project_name+"/"     # ./ 的意思是:当前目录(登录pyspider时)
 44 if not os.path.exists(path_for_project):
 45     os.makedirs(path_for_project)
 46     DIR_PATH = path_for_project
 47 else:
 48     DIR_PATH = path_for_project
 49 #注意哦,“data”文件夹是pyspider启动时自动生成的,其中的db文件是用来默认储存捕获的数据的。但是,我们已经实现了on_result方法把数据传给了Mysql,所以这data文件夹是不起作用的,因此可以忽略。
 50 
 51 #编码转换
 52 reload(sys)     #Python运行的时候首先加载了site.py,在site.py文件里有这么一段代码:
 53                 #    if hasattr(sys, "setdefaultencoding"):
 54                 #        del sys.setdefaultencoding
 55                 #可以看出,在sys加载后,setdefaultencoding方法被删除了,所以我们要通过重新导入sys来设置系统编码
 56 sys.setdefaultencoding('utf8')  #设置默认编码,UTF-8
 57 
 58 
 59 class Handler(BaseHandler):
 60     
 61     headers= {
 62     "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
 63     "Accept-Encoding":"gzip, deflate, sdch",
 64     "Accept-Language":"zh-CN,zh;q=0.8",
 65     "Cache-Control":"max-age=0",
 66     "Connection":"keep-alive",
 67     "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
 68     }
 69 
 70     crawl_config = {
 71         'itag': 'v1.1',     #修改这个tag号,可以重新启动爬取
 72         "headers" : headers,
 73         "timeout" : 100000
 74     }
 75     
 76     
 77     def __init__(self):
 78         self.dir_path = DIR_PATH
 79         self.tool = Tool()
 80     
 81     
 82     @every(minutes=24 * 60)         # @every修饰器,表示每24小时会执行一次
 83     def on_start(self):             # 这里设置你要爬取的网页URL(最好是列表的形式,按更新顺序排列),先登录看看是否对应,否则容易出错
 84         self.crawl(website_url_initial,validate_cert=False, callback=self.index_page)    # self.crawl 告诉 pyspider 抓取指定页面,然后使用 callback 函数对结果进行解析,并调用接下来的index_page
 85 # 总结:
 86 # 通过 on_start 回调函数,作为爬取的入口点,当点击主面板上的 run 的时候,就是调用这个函数,启动抓取。
 87 # self.crawl 告诉调度器,我们需要抓取 '某个url' 这个页面,然后使用 callback=self.index_page 这个回调函数进行解析。
 88 # 所有 return 的内容默认会被捕获到 resultdb 中,可以直接在 WEBUI 上看到(如果结果)。
 89 
 90     
 91     @config(age=10 * 24 * 60 * 60)  #在这表示我们认为 10 天内页面有效,不会再次进行更新抓取
 92     #由此,注意,pyspider不会抓取同一个URL两次(永久丢弃),即使修改了代码,对于第一次运行该项目并修改并第二次运行该项目的初学者来说,这是非常常见的。
 93     #以上是引述。但是,在实际操作WebUI时,通过单步调试可以很方便地抓取同一个页面。
 94     def index_page(self, response):             #设置索引页
 95         for each in response.doc(detail_page_css).items(): 
 96             self.crawl(each.attr.href, validate_cert=False,callback=self.detail_page)
 97         next = response.doc(next_page_css)
 98         self.crawl(next.attr.href,validate_cert=False, connect_timeout = 5000, timeout = 20000,callback=self.index_page)
 99         # validate_cert=False 参数,用来解决SSL证书问题,对于以“https”开头的网站,必须添加
100     
101     @config(priority=2)
102     def detail_page(self, response):
103         # 使用CSS正则表达式工具修改doc()中的路径,进行页面上的元素的采集
104         title = title_css
105         if (title_css != 'null'):
106             title = response.doc(title_css).text()
107         introduction = introduction_css
108         if (introduction_css != 'null'):
109             introduction = response.doc(introduction_css).text()
110         time = time_css
111         if (time_css != 'null'):
112             time = response.doc(time_css).text()
113 #        time = time[10:] #我这里采用了截取字符段的形式,获得真正的时间字符子序列(不通用!!!)
114             datetime_struct = parser.parse(time)
115             time=datetime_struct.strftime('%Y-%m-%d')   # 这里的功能是,将网页代表时间的字符串格式化为%Y-%m-%d(原网页是英文格式)
116         content = content_css
117         if (content_css != 'null'):
118             content = response.doc(content_css).text()
119         keywords = keywords_css
120         if (keywords_css != 'null'):
121             keywords = response.doc(keywords_css).text()            
122         url = response.url
123         picture_url = ''
124         picture_local_path = ''
125         file_title = re.sub('[\/:*?"<>|]','-',title)
126         imgDir = self.dir_path
127         for imgElem in response.doc(img_css).items():
128             imgUrl = imgElem.attr.src
129 #            imgUrl = imgUrl[:-10]  #为了截掉后面多余的字段";width=560",总共10个字符(不通用!!!)
130             if imgUrl and self.tool.get_name(imgUrl) != 'logo':  #这个网站每个网页都莫名其妙地爬两个logo图片下来,因此要过滤掉(不通用!!!)
131                 picture_url += imgUrl + ';'  #picture_url和picture_local_path都需要滞后于这个过滤操作
132                 #获取图片文件后缀
133                 extension = self.tool.get_extension(imgUrl)
134                 name = self.tool.get_name(imgUrl)
135                 #拼接图片名
136                 file_name = name + "." + extension
137                 picture_local_path += ';' + file_name
138                 self.crawl(imgUrl,callback=self.save_img,save={"file_name":file_name, "imgDir":imgDir},validate_cert=False, connect_timeout = 5000, timeout = 20000)   
139                 # 这里回调了save_img函数,在单步调试时可以明显看到
140 
141     # def detail_page(self, response)作为结果返回一个对象。
142     # 结果将被resultdb默认捕获。
143     # 可以通过覆盖on_result(self, result)自己管理结果的方法。        
144         return {    # 与你建立的表结构对应。这是python中的字典结构,即“键-值对”
145             "title":title,
146             "introduction":introduction,
147             "time":time,
148             "content":content,
149             "keywords":keywords,
150             "name":project_name,      #这里根据你建的表格名修改
151             "source":source_declaration,
152             "url":url,
153             "picture_url":'null' if picture_url == '' else picture_url,
154             "picture_local_path":'null' if picture_local_path == '' else picture_local_path
155         }
156 
157     
158     #保存图片
159     def save_img(self,response):    # 可以看到,上面save中保存的内容其实通过response传了过来
160         content = response.content  # resp.content返回的是bytes型也就是二进制的数据,resp.text返回的是Unicode型的数据。
161                                     # 简而言之,如果你想取文本,可以通过r.text。    如果想取图片,文件,则可以通过r.content。
162         file_name = response.save["file_name"]
163         imgDir = response.save["imgDir"]
164         file_path = imgDir + file_name
165         self.tool.save_img(content,imgDir,file_path)
166     
167     #数据存储函数:on_result方法
168     def on_result(self,result):         
169         if not result or not result['title']:   # 如果没到最后,继续返回数据
170             return
171         sql = SQL()     # 覆盖默认方法,使用mysqldb文件中定义的方法,连接数据库
172         sql.insert(project_name,**result)  #将结果插入到表格。同理,这里根据你建的表格名修改    
173         
174     
175 #工具类    
176 class Tool:
177     #保存图片
178     def save_img(self,content,imgDir,path):
179         if not os.path.exists(imgDir):  # os.path.exists(name)判断是否存在文件或目录name
180             os.makedirs(imgDir)  # os.makedirs() 方法用于递归创建目录
181         f = open(path,"wb" )     # wb 以只写方式打开
182         f.write(content)        # 写入文件
183         f.close()
184 
185     #获取url后缀名
186     def get_extension(self,url):                            
187         extension = url.split(".")[-1]
188         return extension 
189     
190     #获取图片名
191     def get_name(self,url):
192         name=url.split("/")[-1].split(".")[0]
193         return name

 

 

7.forcompositesworld(复合材料世界)基于JEC通用化代码模板_改进

  1 #!/usr/bin/env python
  2 # -*- encoding: utf-8 -*-
  3 # Created on 2018-03-19 22:26:12
  4 # Project: Model
  5 #问题:
  6 #1. ValueError(u'String does not contain a date)。time的抓取规则仍待改善。对于特别难分离的日期,需要更先进的手段。  ---已解决,注意首先要选择合适、准确、无歧义的CSS表达式。再进行时间格式的处理!或者选取更合适的日期项,如在首页中选择。
  7 #2. 仍然有少量OpenSSL connet SSL_ERROR_SYSCALL型的错误。
  8 
  9 
 10 #**********************************************************************************----------~~~~~~~~\
 11 #伪宏控制__范式编程
 12 #------(理论上)你只需要在这里[正确]填入所有信息,整个程序即可运行!【只适用于单一index的爬取。多重分类页面,或者需要对采集的数据做进一步规范化,则必须在后面相应地方改进】
 13 project_name = "compositesworld"        #你的项目 的名称
 14 website_url_initial = 'https://www.compositesworld.com/news/list'  #你爬取的初始网页(index页) 的地址
 15 detail_page_css = '.headline > a'                           #新闻页面链接     的CSS表达式
 16 next_page_css = 'a[aria-label="Next"]'                          #下一页链接  的CSS表达式
 17 title_css = '.content-headline'                                 #新闻标题       的CSS表达式
 18 introduction_css = '.col-sm-12 > h1'                    #新闻简介       的CSS表达式
 19 time_css = '.clearfix span[property="dc:created"]'                     #发布时间       的CSS表达式
 20 content_css = '#short > div > div > p'      #新闻内容       的CSS表达式
 21 img_css = 'picture > img'                               #新闻图片       的CSS表达式
 22 keywords_css = 'null'                                       #关键词,一般页面中无,因此默认为空。#!【重要:如果其他的 *_css 在网页中也找不到对应项的话,可以填'null',程序将自动返回空值】
 23 source_declaration = "原创"                                   #原创声明,一般不改动
 24 #**********************************************************************************-----------~~~~~~~/
 25 
 26 from pyspider.libs.base_handler import *        #这个库中定义了爬取的各种控制函数和方法
 27 import re   #re就是regular expression,即正则表达式。正则表达式(通项公式)是用来简洁表达一组字符串的表达式。优势是简洁,一行胜千言。这个库主要用于字符串匹配。
 28 from pyspider.database.mysql.mysqldb import SQL
 29 from pyspider.database.mysql.mysqldb_new import SQL as SQL_new
 30 import sys      #用于接下来修改编码格式
 31 import os       #OS库提供了使用各种操作系统功能的接口
 32 import time as ti       # 用于延时控制
 33 from dateutil import parser       #日期处理库,parser子库是根据字符串解析成datetime
 34 
 35 #根据项目名称,自动创建表
 36 sql_new = SQL_new()
 37 sql_new.create_table(project_name)
 38 
 39 
 40 #图片存放目录【在当前目录自动创建项目子目录,分类各项目的爬取内容。可实现多项目的同时爬取,而内容分开】
 41 path_for_project = "./"+project_name+"/"     # ./ 的意思是:当前目录(登录pyspider时)
 42 if not os.path.exists(path_for_project):
 43     os.makedirs(path_for_project)
 44     DIR_PATH = path_for_project
 45 else:
 46     DIR_PATH = path_for_project
 47 #注意哦,“data”文件夹是pyspider启动时自动生成的,其中的db文件是用来默认储存捕获的数据的。但是,我们已经实现了on_result方法把数据传给了Mysql,所以这data文件夹是不起作用的,因此可以忽略。
 48 
 49 #编码转换
 50 reload(sys)     #Python运行的时候首先加载了site.py,在site.py文件里有这么一段代码:
 51                 #    if hasattr(sys, "setdefaultencoding"):
 52                 #        del sys.setdefaultencoding
 53                 #可以看出,在sys加载后,setdefaultencoding方法被删除了,所以我们要通过重新导入sys来设置系统编码
 54 sys.setdefaultencoding('utf8')  #设置默认编码,UTF-8
 55 
 56 
 57 class Handler(BaseHandler):
 58     
 59     headers= {
 60     "Accept":"text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
 61     "Accept-Encoding":"gzip, deflate, sdch",
 62     "Accept-Language":"zh-CN,zh;q=0.8",
 63     "Cache-Control":"max-age=0",
 64     "Connection":"keep-alive",
 65     "User-Agent":"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/41.0.2272.101 Safari/537.36"
 66     }
 67 
 68     crawl_config = {
 69         'itag': 'v1.1',     #修改这个tag号,可以重新启动爬取
 70         "headers" : headers,
 71         "timeout" : 100000
 72     }
 73     
 74     
 75     def __init__(self):
 76         self.dir_path = DIR_PATH
 77         self.tool = Tool()
 78     
 79     
 80     @every(minutes=24 * 60)         # @every修饰器,表示每24小时会执行一次
 81     def on_start(self):             # 这里设置你要爬取的网页URL(最好是列表的形式,按更新顺序排列),先登录看看是否对应,否则容易出错
 82         self.crawl(website_url_initial,validate_cert=False, callback=self.index_page)    # self.crawl 告诉 pyspider 抓取指定页面,然后使用 callback 函数对结果进行解析,并调用接下来的index_page
 83 # 总结:
 84 # 通过 on_start 回调函数,作为爬取的入口点,当点击主面板上的 run 的时候,就是调用这个函数,启动抓取。
 85 # self.crawl 告诉调度器,我们需要抓取 '某个url' 这个页面,然后使用 callback=self.index_page 这个回调函数进行解析。
 86 # 所有 return 的内容默认会被捕获到 resultdb 中,可以直接在 WEBUI 上看到(如果结果)。
 87 
 88     
 89     @config(age=10 * 24 * 60 * 60)  #在这表示我们认为 10 天内页面有效,不会再次进行更新抓取
 90     #由此,注意,pyspider不会抓取同一个URL两次(永久丢弃),即使修改了代码,对于第一次运行该项目并修改并第二次运行该项目的初学者来说,这是非常常见的。
 91     #以上是引述。但是,在实际操作WebUI时,通过单步调试可以很方便地抓取同一个页面。
 92     def index_page(self, response):             #设置索引页
 93         for each in response.doc(detail_page_css).items(): 
 94             self.crawl(each.attr.href, validate_cert=False,callback=self.detail_page)
 95         next = response.doc(next_page_css)
 96         self.crawl(next.attr.href,validate_cert=False, connect_timeout = 5000, timeout = 20000,callback=self.index_page)
 97         # validate_cert=False 参数,用来解决SSL证书问题,对于以“https”开头的网站,必须添加
 98     
 99     @config(priority=2)
100     def detail_page(self, response):
101         # 使用CSS正则表达式工具修改doc()中的路径,进行页面上的元素的采集
102         title = title_css
103         if (title_css != 'null'):
104             title = response.doc(title_css).text()
105         introduction = introduction_css
106         if (introduction_css != 'null'):
107             introduction = response.doc(introduction_css).text()
108         time = time_css         #以下都是在改日期判断
109         if (time_css != 'null'):
110             time = response.doc(time_css).text()
111             time.strip()  #先作去空格处理
112             time = time[10:] #我这里采用了截取字符段的形式,获得真正的时间字符子序列(不通用!!!)
113             datetime_struct = parser.parse(time)
114             time=datetime_struct.strftime('%Y-%m-%d')   # 这里的功能是,将网页代表时间的字符串格式化为%Y-%m-%d(原网页是英文格式)
115         content = content_css
116         if (content_css != 'null'):
117             content = response.doc(content_css).text()
118         keywords = keywords_css
119         if (keywords_css != 'null'):
120             keywords = response.doc(keywords_css).text()            
121         url = response.url
122         picture_url = ''
123         picture_local_path = ''
124         file_title = re.sub('[\/:*?"<>|]','-',title)
125         imgDir = self.dir_path
126         for imgElem in response.doc(img_css).items():
127             imgUrl = imgElem.attr.src
128             imgUrl = imgUrl[:-10]  #为了截掉后面多余的字段";width=560",总共10个字符(不通用!!!)
129             if imgUrl:  
130                 picture_url += imgUrl + ';'  #picture_url和picture_local_path都需要滞后于这个过滤操作
131                 #获取图片文件后缀
132                 extension = self.tool.get_extension(imgUrl)
133                 name = self.tool.get_name(imgUrl)
134                 #拼接图片名
135                 file_name = name + "." + extension
136                 picture_local_path += ';' + file_name
137                 self.crawl(imgUrl,callback=self.save_img,save={"file_name":file_name, "imgDir":imgDir},validate_cert=False, connect_timeout = 5000, timeout = 20000)   
138                 # 这里回调了save_img函数,在单步调试时可以明显看到
139 
140     # def detail_page(self, response)作为结果返回一个对象。
141     # 结果将被resultdb默认捕获。
142     # 可以通过覆盖on_result(self, result)自己管理结果的方法。        
143         return {    # 与你建立的表结构对应。这是python中的字典结构,即“键-值对”
144             "title":title,
145             "introduction":introduction,
146             "time":time,
147             "content":content,
148             "keywords":keywords,
149             "name":project_name,      #这里根据你建的表格名修改
150             "source":source_declaration,
151             "url":url,
152             "picture_url":'null' if picture_url == '' else picture_url,
153             "picture_local_path":'null' if picture_local_path == '' else picture_local_path
154         }
155 
156     
157     #保存图片
158     def save_img(self,response):    # 可以看到,上面save中保存的内容其实通过response传了过来
159         content = response.content  # resp.content返回的是bytes型也就是二进制的数据,resp.text返回的是Unicode型的数据。
160                                     # 简而言之,如果你想取文本,可以通过r.text。    如果想取图片,文件,则可以通过r.content。
161         file_name = response.save["file_name"]
162         imgDir = response.save["imgDir"]
163         file_path = imgDir + file_name
164         self.tool.save_img(content,imgDir,file_path)
165     
166     #数据存储函数:on_result方法
167     def on_result(self,result):         
168         if not result or not result['title']:   # 如果没到最后,继续返回数据
169             return
170         sql = SQL()     # 覆盖默认方法,使用mysqldb文件中定义的方法,连接数据库
171         sql.insert(project_name,**result)  #将结果插入到表格。同理,这里根据你建的表格名修改    
172         
173     
174 #工具类    
175 class Tool:
176     #保存图片
177     def save_img(self,content,imgDir,path):
178         if not os.path.exists(imgDir):  # os.path.exists(name)判断是否存在文件或目录name
179             os.makedirs(imgDir)  # os.makedirs() 方法用于递归创建目录
180         f = open(path,"wb" )     # wb 以只写方式打开
181         f.write(content)        # 写入文件
182         f.close()
183 
184     #获取url后缀名
185     def get_extension(self,url):                            
186         extension = url.split(".")[-1]
187         return extension 
188     
189     #获取图片名
190     def get_name(self,url):
191         name=url.split("/")[-1].split(".")[0]
192         return name

 

 

8.testpro通过调用MySQLnew实现自动创建列表_demo

1 from pyspider.database.mysql.mysqldb_new import SQL
2 
3 sql = SQL()        #定义一个SQL对象
4 sql.create_table("test_for_auto_table_maker")    #用这个对象的create_table方法创建表格,表名为"test_for_auto_table_maker"

 

 

9.mysqldb_new(库)

 1 #!/usr/bin/env python
 2 # -*- encoding: utf-8 -*-
 3 #【备注:使用该改进方法可能需要安装的库:sqlalchemy,mysql-connector。均可用pip install快速安装】
 4 
 5 
 6 from six import itervalues
 7 import MySQLdb
 8 from sqlalchemy import *
 9 from sqlalchemy.orm import *
10 from sqlalchemy.databases import mysql
11 #from sqlalchemy.ext.declarative import declarative_base
12 
13 #利用MySQLdb来建立一个名字是变量的表实在太困难了
14 #因此采用了另一个库:sqlalchemy
15 
16 class SQL():
17     def __init__(self):
18         #数据库初始化
19         #数据库连接相关信息(全局化处理)【要实现自动创建表格,必须注意调节create_table中的连接参数信息】
20         hosts    = 'localhost'
21         username = 'root'
22         password = '233333'
23         database = 'pyspider'
24         charsets = 'utf8'
25         port_number = 3307
26         self.connection = False
27         try:
28             self.conn = MySQLdb.connect(host = hosts,user = username,passwd = password,db = database,charset = charsets, port = port_number)
29             self.cursor = self.conn.cursor()
30             self.cursor.execute("set names "+charsets)
31             self.connection = True
32         except Exception,e:
33             print "Cannot Connect To Mysql!/n",e
34 
35     def escape(self,string):
36         return '%s' % string
37     #插入数据到数据库
38     def insert(self,tablename=None,**values):
39 
40         if self.connection:
41             tablename = self.escape(tablename)
42             if values:
43                 _keys = ",".join(self.escape(k) for k in values)
44                 _values = ",".join(['%s',]*len(values))
45                 sql_query = "insert into %s (%s) values (%s)" % (tablename,_keys,_values)
46             else:
47                 sql_query = "replace into %s default values" % tablename
48             try:
49                 if values:
50                     self.cursor.execute(sql_query,list(itervalues(values)))
51                 else:
52                     self.cursor.execute(sql_query)
53                 self.conn.commit()
54                 return True
55             except Exception,e:
56                 print "An Error Occured: ",e
57                 return False
58     # 用于建立表格,可能之后需要加强try-except机制
59     # 【经测试,该方法不会覆盖掉已经创建过的表格】
60     def create_table(self,project_name):
61         #定义引擎
62         engine = create_engine('mysql+mysqlconnector://root:fdzxks@localhost:3307/pyspider')        # 这里的引擎与上面的连接参数要相应一致
63         #绑定元信息
64         metadata = MetaData(engine)
65         #创建表格,初始化数据库
66         user = Table(project_name, metadata,
67             Column('title', VARCHAR(255)),
68             Column('introduction', mysql.MSLongText),
69             Column('time', VARCHAR(255)),
70             Column('content', mysql.MSLongText),
71             Column('keywords', VARCHAR(255)),
72             Column('name', VARCHAR(255)),
73             Column('source', VARCHAR(255)),
74             Column('url', VARCHAR(255)),
75             Column('picture_url', mysql.MSLongText),
76             Column('picture_local_path', mysql.MSLongText),
77                     )
78         #http://blog.csdn.net/FeiSan/article/details/1887677。教程:SQLAlchemy下定义MySQL特有的字段类型。
79         #创建数据表,如果数据表存在则忽视
80         metadata.create_all(engine)
81         #获取数据库链接,以备后面使用
82         conn = engine.connect()