1.當獲取https連接是須要添加參數 validate_cert=False。css
2.增長翻頁操做html
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/node
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.python
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(複合材料世界)爬蟲程序_詳註mysql
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)僞宏控制__範式編web
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實現自動建立列表_demosql
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()