├── DomzSpider.py ├── README.md ├── back_end.php ├── build ├── build.js ├── check-versions.js ├── dev-client.js ├── dev-server.js ├── utils.js ├── vue-loader.conf.js ├── webpack.base.conf.js ├── webpack.dev.conf.js ├── webpack.prod.conf.js └── webpack.test.conf.js ├── config ├── dev.env.js ├── index.js ├── prod.env.js └── test.env.js ├── dist ├── index.html └── static │ ├── css │ ├── app.bc6bcebd8dff1469ed2a180d243d1fb1.css │ └── app.bc6bcebd8dff1469ed2a180d243d1fb1.css.map │ └── js │ ├── app.2e2f3fd3b6a1a7409115.js │ ├── app.2e2f3fd3b6a1a7409115.js.map │ ├── manifest.42e3257fe0dc6f03a838.js │ ├── manifest.42e3257fe0dc6f03a838.js.map │ ├── vendor.080f64fd4ca0f1bcf027.js │ └── vendor.080f64fd4ca0f1bcf027.js.map ├── image ├── img1.png ├── img2.png ├── img3.png └── img4.png ├── index.html ├── jsonToMySQL.py ├── package.json ├── src ├── App.vue ├── assets │ └── logo.png ├── components │ ├── searchEngine.vue │ └── searchResult.vue ├── main.js └── router │ └── index.js ├── test ├── e2e │ ├── custom-assertions │ │ └── elementCount.js │ ├── nightwatch.conf.js │ ├── runner.js │ └── specs │ │ └── test.js └── unit │ ├── index.js │ ├── karma.conf.js │ └── specs │ └── Hello.spec.js └── urlToKeywords.py /DomzSpider.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | #from scrapy.spider import BaseSpider 3 | from scrapy.contrib.spiders import CrawlSpider,Rule 4 | from scrapy.contrib.linkextractors.sgml import SgmlLinkExtractor 5 | from scrapy.dupefilter import RFPDupeFilter 6 | from scrapy.selector import HtmlXPathSelector 7 | from searchEngine.items import SearchengineItem 8 | class DmozSpider(CrawlSpider): 9 | name = "dmoz" 10 | allowed_domains = [ 11 | "news.cn", 12 | "news.xinhuanet.com" 13 | ] 14 | start_urls = [ 15 | "http://www.news.cn/", 16 | "http://www.news.cn/mil/index.htm", 17 | "http://www.news.cn/politics/" 18 | "http://www.news.cn/world/index.htm", 19 | "http://www.news.cn/tech/index.htm" 20 | ] 21 | rules = ( 22 | #Rule(SgmlLinkExtractor(allow=('page/[0-9]+', ))), 23 | #Rule(SgmlLinkExtractor(allow=['/' ]),'item_parse') 24 | Rule(SgmlLinkExtractor(allow=('/', )),callback='item_parse'), 25 | ) 26 | def item_parse(self,response,dont_filter=False): 27 | #self.log("%s"%response.url) 28 | item = SearchengineItem() 29 | item['url'] = response.url 30 | item['title'] = response.selector.xpath('//title/text()').extract() 31 | item['keywords'] = response.selector.xpath('//meta[@name="keywords"]/@content').extract() 32 | item['description'] = response.selector.xpath('//meta[@name="description"]/@content').extract() 33 | for t in item['title']: 34 | print t.encode('utf-8') 35 | for t in item['keywords']: 36 | print t.encode('utf-8') 37 | for t in item['description']: 38 | print t.encode('utf-8') 39 | return item 40 | 41 | #print item['title'] 42 | ''' 43 | def parse(self, response): 44 | #hxs = HtmlXPathSelector(response) 45 | #sites = hxs.select('//head') 46 | #res = HtmlXPathSelector(response) 47 | 48 | item = SearchengineItem() 49 | #for site in sites: 50 | # item = SearchengineItem() 51 | # item['title'] = site.select('//title/text()').extract() 52 | # item['link'] = site.select('meta/@keywords').extract() 53 | #item['desc'] = site.select('text()').extract() 54 | #items.append(item) 55 | item['title'] = response.selector.xpath('//title/text()').extract() 56 | item['keywords'] = response.selector.xpath('//meta[@name="keywords"]/@content').extract() 57 | item['description'] = response.selector.xpath('//meta[@name="description"]/@content').extract() 58 | for t in item['title']: 59 | print t.encode('utf-8') 60 | for t in item['keywords']: 61 | print t.encode('utf-8') 62 | for t in item['description']: 63 | print t.encode('utf-8') 64 | #print item['title'] 65 | return item 66 | 67 | ''' 68 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # 小型搜索引擎(tinySearchEngine) 2 | 3 | > 基于scrapy爬虫框架,结巴分词,php和vue.js实现的小型搜索引擎。 4 | > 5 | > a tiny search engine based on vue.js and use scrapy,jieba,php to accomplish it 6 | 7 | ### Build Setup 8 | 9 | ``` bash 10 | # install dependencies 11 | npm install 12 | 13 | # serve with hot reload at localhost:8080 14 | npm run dev 15 | 16 | # build for production with minification 17 | npm run build 18 | 19 | # build for production and view the bundle analyzer report 20 | npm run build --report 21 | ``` 22 | 23 | ### 整体实现 24 | 25 | 大体流程如下: 26 | 27 | 1.爬虫爬取网页数据,保存在文件中, 28 | 29 | 2.python读取文件内容,存到数据库表中,使用结巴分词对网页内容进行分词,并获得TF-IDF值,构建倒排索引保存到数据库中。 30 | 31 | 3.前端界面接受用户输入,使用POST请求将数据发送到后端。 32 | 33 | 4.后端接受到数据进行分词,然后在倒排索引数据库查询,结果取并集,然后根据倒排索引数据库结果在结果数据库中查询,返回网页的具体信息。 34 | 35 | 5.前端收到返回后,将结果呈现出来。 36 | 37 | ### 具体实现 38 | 39 | #### 1.爬虫 40 | 41 | 爬虫采用的是python的爬虫库scrapy,只需要进行简单的配置就可以使用,如果要递归爬取,可以采用`class DmozSpider(CrawlSpider)`。 42 | 43 | 要获得的数据网页数据主要有:url,title,description,keywords,具体配置如下: 44 | 45 | ```python 46 | item['title'] = response.selector.xpath('//title/text()').extract() 47 | item['keywords'] = response.selector.xpath('//meta[@name="keywords"]/@content').extract() 48 | item['description'] = response.selector.xpath('//meta[@name="description"]/@content').extract() 49 | ``` 50 | 51 | 同时,为了保存数据,需要定义items,在items.py中添加如下: 52 | 53 | ```python 54 | url = scrapy.Field() 55 | title = scrapy.Field() 56 | keywords = scrapy.Field() 57 | description = scrapy.Field() 58 | ``` 59 | 60 | 在终端中运行`scrapy crawl dmoz -o items.json -t json`,可以把数据存到items.json中。 61 | 62 | #### 2.分词 63 | 64 | 分词我选用的是python环境下的[结巴分词](https://github.com/fxsjy/jieba), 在考虑了好几种分词后,最后选择了结巴分词,主要是安装简单(可以直接通过pip安装),使用方便,并且在社区的贡献下,衍生出了不同语言版本(在后端中,我采用的是结巴分词的php版本)。 65 | 66 | 结巴分词直接提供了基于TF-IDF算法的关键词提取功能: 67 | 68 | > jieba.analyse.extract_tags(sentence, topK=20, withWeight=False, allowPOS=()) 69 | > 70 | > sentence 为待提取的文本 71 | > 72 | > topK 为返回几个 TF/IDF 权重最大的关键词,默认值为 20 73 | > 74 | > withWeight 为是否一并返回关键词权重值,默认值为 Falseallow 75 | > 76 | > POS 仅包括指定词性的词,默认值为空,即不筛选 77 | 78 | 所以在分词过程中,可以直接通过结巴分词获得关键词,以及关键词对应的TF-IDF值。 79 | 80 | #### 3.数据库 81 | 82 | 数据库选择的是MySQL,新建数据库名`python`,数据库下有两个表,`search_result`,`inverted index`。 83 | 84 | ``` 85 | ├── python //数据库          86 | │   ├── search_result        //搜索结果 87 | │   └── inverted indexsuoyin //倒排索引 88 | ``` 89 | 90 | 经过爬虫爬取的数据保存在items.json中,在jsonToMySQL.py中,将文件中保存的数据存到数据库表search_result中,有index作为网页的唯一标志,字段有`index_`,`url`,`title`,`date`,`description`。 91 | 92 | 在urlToKeywords.py中,从表search_result中读取每一条,利用结巴分词提取关键字,并获得每个关键词的TF-IDF值,保存到表`inverted index`中,在查询的过程中,输入一条语句,将这条语句分词后得到关键词,将每个关键词进inverted index中查询,得到index和TF-IDF,结果取并集,根据index到search_result查询url,title等信息,利用TF-IDF之和进行页面的排序。 93 | 94 | #### 4.前端 95 | 96 | 前端采用前端框架`vue.js`,`使用vue-router`实现路由管理,使用`axios`发送http请求。组件有两个,模仿的是百度的首页,在有输入的时候输入框位置变化(百度打开时输入框居中,有输入的时候变换到输入框在顶部),百度应该是用切换css类的方式来实现的,我采用的是切换组件,首页输入框有输入改变触发`{{n}} 135 | ``` 136 | 137 | 结果显示 138 | 139 | ```html 140 |
141 | {{ item.title}} 142 |

{{ item.description }}

143 |
  • {{ item.url }}
  • 144 |
  •  {{ item.date }}
  • 145 |
    146 | ``` 147 | 148 | 利用计算属性,只显示十个结果,并根据当前页的不同显示不同的结果。 149 | 150 | ```javascript 151 | part_response: function(){ 152 | var part=[] 153 | for(let start = (this.page_select-1)*10;startquery($sql); 33 | 34 | if(!$result){ 35 | echo json_encode(""); 36 | //echo "sql语句错误
    "; 37 | //echo "error:".$mysqli->error."|".$mysqli->error; 38 | } 39 | $num_results = $result -> num_rows; //结果行数 40 | //echo "

    Number of row found: ". $num_results ."

    ";//输出行数 41 | global $result_array; 42 | for($i = 0;$i < $num_results;$i++)//循环输出每组元素 43 | { 44 | $row = $result -> fetch_assoc();//提取元素,一次一行,fetch_assoc()提取出的元素,有属性以及值 45 | $index_ = stripcslashes(($row['index_'])); 46 | $tf_idf = stripcslashes($row['tf_idf']); 47 | //echo $index_." ".$tf_idf." "; 48 | if(array_key_exists($index_,$result_array)){ 49 | $result_array[$index_]+=$tf_idf; 50 | } 51 | else{ 52 | $result_array[$index_] = 0+$tf_idf; 53 | } 54 | } 55 | 56 | //mysqli_close($link); 57 | } 58 | function search($index){ 59 | global $return_array; 60 | //$link = mysqli_connect("localhost", "root", "666666", "python"); 61 | global $link; 62 | mysqli_set_charset($link, "utf8"); 63 | /* check connection */ 64 | if (mysqli_connect_errno()) { 65 | echo json_encode(""); 66 | exit(); 67 | } 68 | 69 | $sql = "select * from `search_result` where index_='".$index."'"; 70 | 71 | $result=$link->query($sql); 72 | 73 | $num_results = $result -> num_rows; //结果行数 74 | $row = $result -> fetch_assoc();//提取元素,一次一行,fetch_assoc()提取出的元素,有属性以及值 75 | $url = stripcslashes(($row['url'])); 76 | $title = stripcslashes($row['title']); 77 | $description = stripcslashes($row['description']); 78 | $date = stripcslashes($row['date']); 79 | $return_array[]=array("url"=>$url,"title"=>$title,"description"=>$description,"date"=>$date); 80 | //mysqli_close($link); 81 | } 82 | session_start(); 83 | 84 | // $_POST['question']='大约'; 85 | if($_POST['question']!=""){ 86 | //$_SESSION["Jie"]=serialize(Jieba::return_self()); 87 | //unserialize($_SESSION["Jie"])::init(); 88 | Jieba::init(); 89 | Finalseg::init(); 90 | //open database 91 | $link = mysqli_connect("localhost", "root", "666666", "python"); 92 | 93 | 94 | $result_array=[]; 95 | $return_array=[]; 96 | $seg_list=Jieba::cutForSearch($_POST['question']); 97 | //$seg_list = unserialize($_SESSION["Jie"])::cutForSearch($_POST['question']); 98 | //var_dump($seg_list); 99 | if(count($seg_list)==0){ 100 | echo json_encode(""); 101 | exit(); 102 | } 103 | foreach ($seg_list as $value){ 104 | //print($value." "); 105 | find($value); 106 | } 107 | if(count($result_array)==0){ 108 | echo json_encode(""); 109 | exit(); 110 | } 111 | arsort($result_array); 112 | foreach ($result_array as $key=>$value){ 113 | search($key); 114 | } 115 | if(count($return_array)==0){ 116 | echo json_encode(""); 117 | exit(); 118 | } 119 | echo json_encode($return_array); 120 | 121 | //close database 122 | mysqli_close($link); 123 | 124 | } 125 | ?> 126 | -------------------------------------------------------------------------------- /build/build.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | process.env.NODE_ENV = 'production' 4 | 5 | var ora = require('ora') 6 | var rm = require('rimraf') 7 | var path = require('path') 8 | var chalk = require('chalk') 9 | var webpack = require('webpack') 10 | var config = require('../config') 11 | var webpackConfig = require('./webpack.prod.conf') 12 | 13 | var spinner = ora('building for production...') 14 | spinner.start() 15 | 16 | rm(path.join(config.build.assetsRoot, config.build.assetsSubDirectory), err => { 17 | if (err) throw err 18 | webpack(webpackConfig, function (err, stats) { 19 | spinner.stop() 20 | if (err) throw err 21 | process.stdout.write(stats.toString({ 22 | colors: true, 23 | modules: false, 24 | children: false, 25 | chunks: false, 26 | chunkModules: false 27 | }) + '\n\n') 28 | 29 | console.log(chalk.cyan(' Build complete.\n')) 30 | console.log(chalk.yellow( 31 | ' Tip: built files are meant to be served over an HTTP server.\n' + 32 | ' Opening index.html over file:// won\'t work.\n' 33 | )) 34 | }) 35 | }) 36 | -------------------------------------------------------------------------------- /build/check-versions.js: -------------------------------------------------------------------------------- 1 | var chalk = require('chalk') 2 | var semver = require('semver') 3 | var packageConfig = require('../package.json') 4 | var shell = require('shelljs') 5 | function exec (cmd) { 6 | return require('child_process').execSync(cmd).toString().trim() 7 | } 8 | 9 | var versionRequirements = [ 10 | { 11 | name: 'node', 12 | currentVersion: semver.clean(process.version), 13 | versionRequirement: packageConfig.engines.node 14 | }, 15 | ] 16 | 17 | if (shell.which('npm')) { 18 | versionRequirements.push({ 19 | name: 'npm', 20 | currentVersion: exec('npm --version'), 21 | versionRequirement: packageConfig.engines.npm 22 | }) 23 | } 24 | 25 | module.exports = function () { 26 | var warnings = [] 27 | for (var i = 0; i < versionRequirements.length; i++) { 28 | var mod = versionRequirements[i] 29 | if (!semver.satisfies(mod.currentVersion, mod.versionRequirement)) { 30 | warnings.push(mod.name + ': ' + 31 | chalk.red(mod.currentVersion) + ' should be ' + 32 | chalk.green(mod.versionRequirement) 33 | ) 34 | } 35 | } 36 | 37 | if (warnings.length) { 38 | console.log('') 39 | console.log(chalk.yellow('To use this template, you must update following to modules:')) 40 | console.log() 41 | for (var i = 0; i < warnings.length; i++) { 42 | var warning = warnings[i] 43 | console.log(' ' + warning) 44 | } 45 | console.log() 46 | process.exit(1) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /build/dev-client.js: -------------------------------------------------------------------------------- 1 | /* eslint-disable */ 2 | require('eventsource-polyfill') 3 | var hotClient = require('webpack-hot-middleware/client?noInfo=true&reload=true') 4 | 5 | hotClient.subscribe(function (event) { 6 | if (event.action === 'reload') { 7 | window.location.reload() 8 | } 9 | }) 10 | -------------------------------------------------------------------------------- /build/dev-server.js: -------------------------------------------------------------------------------- 1 | require('./check-versions')() 2 | 3 | var config = require('../config') 4 | if (!process.env.NODE_ENV) { 5 | process.env.NODE_ENV = JSON.parse(config.dev.env.NODE_ENV) 6 | } 7 | 8 | var opn = require('opn') 9 | var path = require('path') 10 | var express = require('express') 11 | var webpack = require('webpack') 12 | var proxyMiddleware = require('http-proxy-middleware') 13 | var webpackConfig = process.env.NODE_ENV === 'testing' 14 | ? require('./webpack.prod.conf') 15 | : require('./webpack.dev.conf') 16 | 17 | // default port where dev server listens for incoming traffic 18 | var port = process.env.PORT || config.dev.port 19 | // automatically open browser, if not set will be false 20 | var autoOpenBrowser = !!config.dev.autoOpenBrowser 21 | // Define HTTP proxies to your custom API backend 22 | // https://github.com/chimurai/http-proxy-middleware 23 | var proxyTable = config.dev.proxyTable 24 | 25 | var app = express() 26 | var compiler = webpack(webpackConfig) 27 | 28 | var devMiddleware = require('webpack-dev-middleware')(compiler, { 29 | publicPath: webpackConfig.output.publicPath, 30 | quiet: true 31 | }) 32 | 33 | var hotMiddleware = require('webpack-hot-middleware')(compiler, { 34 | log: () => {} 35 | }) 36 | // force page reload when html-webpack-plugin template changes 37 | compiler.plugin('compilation', function (compilation) { 38 | compilation.plugin('html-webpack-plugin-after-emit', function (data, cb) { 39 | hotMiddleware.publish({ action: 'reload' }) 40 | cb() 41 | }) 42 | }) 43 | 44 | // proxy api requests 45 | Object.keys(proxyTable).forEach(function (context) { 46 | var options = proxyTable[context] 47 | if (typeof options === 'string') { 48 | options = { target: options } 49 | } 50 | app.use(proxyMiddleware(options.filter || context, options)) 51 | }) 52 | 53 | // handle fallback for HTML5 history API 54 | app.use(require('connect-history-api-fallback')()) 55 | 56 | // serve webpack bundle output 57 | app.use(devMiddleware) 58 | 59 | // enable hot-reload and state-preserving 60 | // compilation error display 61 | app.use(hotMiddleware) 62 | 63 | // serve pure static assets 64 | var staticPath = path.posix.join(config.dev.assetsPublicPath, config.dev.assetsSubDirectory) 65 | app.use(staticPath, express.static('./static')) 66 | 67 | var uri = 'http://localhost:' + port 68 | 69 | var _resolve 70 | var readyPromise = new Promise(resolve => { 71 | _resolve = resolve 72 | }) 73 | 74 | console.log('> Starting dev server...') 75 | devMiddleware.waitUntilValid(() => { 76 | console.log('> Listening at ' + uri + '\n') 77 | // when env is testing, don't need open it 78 | if (autoOpenBrowser && process.env.NODE_ENV !== 'testing') { 79 | opn(uri) 80 | } 81 | _resolve() 82 | }) 83 | 84 | var server = app.listen(port) 85 | 86 | module.exports = { 87 | ready: readyPromise, 88 | close: () => { 89 | server.close() 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /build/utils.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var config = require('../config') 3 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 4 | 5 | exports.assetsPath = function (_path) { 6 | var assetsSubDirectory = process.env.NODE_ENV === 'production' 7 | ? config.build.assetsSubDirectory 8 | : config.dev.assetsSubDirectory 9 | return path.posix.join(assetsSubDirectory, _path) 10 | } 11 | 12 | exports.cssLoaders = function (options) { 13 | options = options || {} 14 | 15 | var cssLoader = { 16 | loader: 'css-loader', 17 | options: { 18 | minimize: process.env.NODE_ENV === 'production', 19 | sourceMap: options.sourceMap 20 | } 21 | } 22 | 23 | // generate loader string to be used with extract text plugin 24 | function generateLoaders (loader, loaderOptions) { 25 | var loaders = [cssLoader] 26 | if (loader) { 27 | loaders.push({ 28 | loader: loader + '-loader', 29 | options: Object.assign({}, loaderOptions, { 30 | sourceMap: options.sourceMap 31 | }) 32 | }) 33 | } 34 | 35 | // Extract CSS when that option is specified 36 | // (which is the case during production build) 37 | if (options.extract) { 38 | return ExtractTextPlugin.extract({ 39 | use: loaders, 40 | fallback: 'vue-style-loader' 41 | }) 42 | } else { 43 | return ['vue-style-loader'].concat(loaders) 44 | } 45 | } 46 | 47 | // https://vue-loader.vuejs.org/en/configurations/extract-css.html 48 | return { 49 | css: generateLoaders(), 50 | postcss: generateLoaders(), 51 | less: generateLoaders('less'), 52 | sass: generateLoaders('sass', { indentedSyntax: true }), 53 | scss: generateLoaders('sass'), 54 | stylus: generateLoaders('stylus'), 55 | styl: generateLoaders('stylus') 56 | } 57 | } 58 | 59 | // Generate loaders for standalone style files (outside of .vue) 60 | exports.styleLoaders = function (options) { 61 | var output = [] 62 | var loaders = exports.cssLoaders(options) 63 | for (var extension in loaders) { 64 | var loader = loaders[extension] 65 | output.push({ 66 | test: new RegExp('\\.' + extension + '$'), 67 | use: loader 68 | }) 69 | } 70 | return output 71 | } 72 | -------------------------------------------------------------------------------- /build/vue-loader.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var config = require('../config') 3 | var isProduction = process.env.NODE_ENV === 'production' 4 | 5 | module.exports = { 6 | loaders: utils.cssLoaders({ 7 | sourceMap: isProduction 8 | ? config.build.productionSourceMap 9 | : config.dev.cssSourceMap, 10 | extract: isProduction 11 | }) 12 | } 13 | -------------------------------------------------------------------------------- /build/webpack.base.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | var config = require('../config') 4 | var vueLoaderConfig = require('./vue-loader.conf') 5 | 6 | function resolve (dir) { 7 | return path.join(__dirname, '..', dir) 8 | } 9 | 10 | module.exports = { 11 | entry: { 12 | app: './src/main.js' 13 | }, 14 | output: { 15 | path: config.build.assetsRoot, 16 | filename: '[name].js', 17 | publicPath: process.env.NODE_ENV === 'production' 18 | ? config.build.assetsPublicPath 19 | : config.dev.assetsPublicPath 20 | }, 21 | resolve: { 22 | extensions: ['.js', '.vue', '.json'], 23 | alias: { 24 | 'vue$': 'vue/dist/vue.esm.js', 25 | '@': resolve('src') 26 | } 27 | }, 28 | module: { 29 | rules: [ 30 | { 31 | test: /\.vue$/, 32 | loader: 'vue-loader', 33 | options: vueLoaderConfig 34 | }, 35 | { 36 | test: /\.js$/, 37 | loader: 'babel-loader', 38 | include: [resolve('src'), resolve('test')] 39 | }, 40 | { 41 | test: /\.(png|jpe?g|gif|svg)(\?.*)?$/, 42 | loader: 'url-loader', 43 | options: { 44 | limit: 10000, 45 | name: utils.assetsPath('img/[name].[hash:7].[ext]') 46 | } 47 | }, 48 | { 49 | test: /\.(woff2?|eot|ttf|otf)(\?.*)?$/, 50 | loader: 'url-loader', 51 | options: { 52 | limit: 10000, 53 | name: utils.assetsPath('fonts/[name].[hash:7].[ext]') 54 | } 55 | } 56 | ] 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /build/webpack.dev.conf.js: -------------------------------------------------------------------------------- 1 | var utils = require('./utils') 2 | var webpack = require('webpack') 3 | var config = require('../config') 4 | var merge = require('webpack-merge') 5 | var baseWebpackConfig = require('./webpack.base.conf') 6 | var HtmlWebpackPlugin = require('html-webpack-plugin') 7 | var FriendlyErrorsPlugin = require('friendly-errors-webpack-plugin') 8 | 9 | // add hot-reload related code to entry chunks 10 | Object.keys(baseWebpackConfig.entry).forEach(function (name) { 11 | baseWebpackConfig.entry[name] = ['./build/dev-client'].concat(baseWebpackConfig.entry[name]) 12 | }) 13 | 14 | module.exports = merge(baseWebpackConfig, { 15 | module: { 16 | rules: utils.styleLoaders({ sourceMap: config.dev.cssSourceMap }) 17 | }, 18 | // cheap-module-eval-source-map is faster for development 19 | devtool: '#cheap-module-eval-source-map', 20 | plugins: [ 21 | new webpack.DefinePlugin({ 22 | 'process.env': config.dev.env 23 | }), 24 | // https://github.com/glenjamin/webpack-hot-middleware#installation--usage 25 | new webpack.HotModuleReplacementPlugin(), 26 | new webpack.NoEmitOnErrorsPlugin(), 27 | // https://github.com/ampedandwired/html-webpack-plugin 28 | new HtmlWebpackPlugin({ 29 | filename: 'index.html', 30 | template: 'index.html', 31 | inject: true 32 | }), 33 | new FriendlyErrorsPlugin() 34 | ] 35 | }) 36 | -------------------------------------------------------------------------------- /build/webpack.prod.conf.js: -------------------------------------------------------------------------------- 1 | var path = require('path') 2 | var utils = require('./utils') 3 | var webpack = require('webpack') 4 | var config = require('../config') 5 | var merge = require('webpack-merge') 6 | var baseWebpackConfig = require('./webpack.base.conf') 7 | var CopyWebpackPlugin = require('copy-webpack-plugin') 8 | var HtmlWebpackPlugin = require('html-webpack-plugin') 9 | var ExtractTextPlugin = require('extract-text-webpack-plugin') 10 | var OptimizeCSSPlugin = require('optimize-css-assets-webpack-plugin') 11 | 12 | var env = process.env.NODE_ENV === 'testing' 13 | ? require('../config/test.env') 14 | : config.build.env 15 | 16 | var webpackConfig = merge(baseWebpackConfig, { 17 | module: { 18 | rules: utils.styleLoaders({ 19 | sourceMap: config.build.productionSourceMap, 20 | extract: true 21 | }) 22 | }, 23 | devtool: config.build.productionSourceMap ? '#source-map' : false, 24 | output: { 25 | path: config.build.assetsRoot, 26 | filename: utils.assetsPath('js/[name].[chunkhash].js'), 27 | chunkFilename: utils.assetsPath('js/[id].[chunkhash].js') 28 | }, 29 | plugins: [ 30 | // http://vuejs.github.io/vue-loader/en/workflow/production.html 31 | new webpack.DefinePlugin({ 32 | 'process.env': env 33 | }), 34 | new webpack.optimize.UglifyJsPlugin({ 35 | compress: { 36 | warnings: false 37 | }, 38 | sourceMap: true 39 | }), 40 | // extract css into its own file 41 | new ExtractTextPlugin({ 42 | filename: utils.assetsPath('css/[name].[contenthash].css') 43 | }), 44 | // Compress extracted CSS. We are using this plugin so that possible 45 | // duplicated CSS from different components can be deduped. 46 | new OptimizeCSSPlugin({ 47 | cssProcessorOptions: { 48 | safe: true 49 | } 50 | }), 51 | // generate dist index.html with correct asset hash for caching. 52 | // you can customize output by editing /index.html 53 | // see https://github.com/ampedandwired/html-webpack-plugin 54 | new HtmlWebpackPlugin({ 55 | filename: process.env.NODE_ENV === 'testing' 56 | ? 'index.html' 57 | : config.build.index, 58 | template: 'index.html', 59 | inject: true, 60 | minify: { 61 | removeComments: true, 62 | collapseWhitespace: true, 63 | removeAttributeQuotes: true 64 | // more options: 65 | // https://github.com/kangax/html-minifier#options-quick-reference 66 | }, 67 | // necessary to consistently work with multiple chunks via CommonsChunkPlugin 68 | chunksSortMode: 'dependency' 69 | }), 70 | // split vendor js into its own file 71 | new webpack.optimize.CommonsChunkPlugin({ 72 | name: 'vendor', 73 | minChunks: function (module, count) { 74 | // any required modules inside node_modules are extracted to vendor 75 | return ( 76 | module.resource && 77 | /\.js$/.test(module.resource) && 78 | module.resource.indexOf( 79 | path.join(__dirname, '../node_modules') 80 | ) === 0 81 | ) 82 | } 83 | }), 84 | // extract webpack runtime and module manifest to its own file in order to 85 | // prevent vendor hash from being updated whenever app bundle is updated 86 | new webpack.optimize.CommonsChunkPlugin({ 87 | name: 'manifest', 88 | chunks: ['vendor'] 89 | }), 90 | // copy custom static assets 91 | new CopyWebpackPlugin([ 92 | { 93 | from: path.resolve(__dirname, '../static'), 94 | to: config.build.assetsSubDirectory, 95 | ignore: ['.*'] 96 | } 97 | ]) 98 | ] 99 | }) 100 | 101 | if (config.build.productionGzip) { 102 | var CompressionWebpackPlugin = require('compression-webpack-plugin') 103 | 104 | webpackConfig.plugins.push( 105 | new CompressionWebpackPlugin({ 106 | asset: '[path].gz[query]', 107 | algorithm: 'gzip', 108 | test: new RegExp( 109 | '\\.(' + 110 | config.build.productionGzipExtensions.join('|') + 111 | ')$' 112 | ), 113 | threshold: 10240, 114 | minRatio: 0.8 115 | }) 116 | ) 117 | } 118 | 119 | if (config.build.bundleAnalyzerReport) { 120 | var BundleAnalyzerPlugin = require('webpack-bundle-analyzer').BundleAnalyzerPlugin 121 | webpackConfig.plugins.push(new BundleAnalyzerPlugin()) 122 | } 123 | 124 | module.exports = webpackConfig 125 | -------------------------------------------------------------------------------- /build/webpack.test.conf.js: -------------------------------------------------------------------------------- 1 | // This is the webpack config used for unit tests. 2 | 3 | var utils = require('./utils') 4 | var webpack = require('webpack') 5 | var merge = require('webpack-merge') 6 | var baseConfig = require('./webpack.base.conf') 7 | 8 | var webpackConfig = merge(baseConfig, { 9 | // use inline sourcemap for karma-sourcemap-loader 10 | module: { 11 | rules: utils.styleLoaders() 12 | }, 13 | devtool: '#inline-source-map', 14 | plugins: [ 15 | new webpack.DefinePlugin({ 16 | 'process.env': require('../config/test.env') 17 | }) 18 | ] 19 | }) 20 | 21 | // no need for app entry during tests 22 | delete webpackConfig.entry 23 | 24 | module.exports = webpackConfig 25 | -------------------------------------------------------------------------------- /config/dev.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var prodEnv = require('./prod.env') 3 | 4 | module.exports = merge(prodEnv, { 5 | NODE_ENV: '"development"' 6 | }) 7 | -------------------------------------------------------------------------------- /config/index.js: -------------------------------------------------------------------------------- 1 | // see http://vuejs-templates.github.io/webpack for documentation. 2 | var path = require('path') 3 | 4 | module.exports = { 5 | build: { 6 | env: require('./prod.env'), 7 | index: path.resolve(__dirname, '../dist/index.html'), 8 | assetsRoot: path.resolve(__dirname, '../dist'), 9 | assetsSubDirectory: 'static', 10 | assetsPublicPath: '/', 11 | productionSourceMap: true, 12 | // Gzip off by default as many popular static hosts such as 13 | // Surge or Netlify already gzip all static assets for you. 14 | // Before setting to `true`, make sure to: 15 | // npm install --save-dev compression-webpack-plugin 16 | productionGzip: false, 17 | productionGzipExtensions: ['js', 'css'], 18 | // Run the build command with an extra argument to 19 | // View the bundle analyzer report after build finishes: 20 | // `npm run build --report` 21 | // Set to `true` or `false` to always turn it on or off 22 | bundleAnalyzerReport: process.env.npm_config_report 23 | }, 24 | dev: { 25 | env: require('./dev.env'), 26 | port: 8080, 27 | autoOpenBrowser: true, 28 | assetsSubDirectory: 'static', 29 | assetsPublicPath: '/', 30 | proxyTable: {}, 31 | // CSS Sourcemaps off by default because relative paths are "buggy" 32 | // with this option, according to the CSS-Loader README 33 | // (https://github.com/webpack/css-loader#sourcemaps) 34 | // In our experience, they generally work as expected, 35 | // just be aware of this issue when enabling this option. 36 | cssSourceMap: false 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /config/prod.env.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | NODE_ENV: '"production"' 3 | } 4 | -------------------------------------------------------------------------------- /config/test.env.js: -------------------------------------------------------------------------------- 1 | var merge = require('webpack-merge') 2 | var devEnv = require('./dev.env') 3 | 4 | module.exports = merge(devEnv, { 5 | NODE_ENV: '"testing"' 6 | }) 7 | -------------------------------------------------------------------------------- /dist/index.html: -------------------------------------------------------------------------------- 1 | search-engine
    -------------------------------------------------------------------------------- /dist/static/css/app.bc6bcebd8dff1469ed2a180d243d1fb1.css: -------------------------------------------------------------------------------- 1 | #searchEngine[data-v-e082b27e]{left:30%;top:40%;width:100%;position:fixed;z-index:1;background-color:#fff}#text[data-v-e082b27e]{width:30%;height:41px;//border-style:solid;//border-width:1px;border:1px solid #39f;font-size:24px;padding:0;margin:-1px 0 0}#button[data-v-e082b27e]{//float:right;height:45px;width:7%;background-color:#39f;border-width:1px;border-style:solid;font-size:24px;color:#fff;margin:-2px 0 0 -5px;padding:0}.hightLight[data-v-17d40f1c]{color:red}#searchResult[data-v-17d40f1c]{width:100%;height:100%;margin:0;padding:0}#header[data-v-17d40f1c]{margin-top:0;padding:0;width:100%;height:80px;background-color:#fff;position:fixed;top:0;left:0;z-index:1}#input[data-v-17d40f1c]{width:600px;height:35px;border:1px solid #39f;font-size:24px;position:relative;left:15%;top:8px}#submit[data-v-17d40f1c]{height:40px;width:120px;background-color:#39f;border:none;//border-style:solid;font-size:24px;color:#fff;margin-top:-1px;//margin-left:-10px;position:relative;top:8px;left:10%}#result[data-v-17d40f1c]{height:auto;width:40%;margin-top:80px;position:relative;left:15%}#result_number[data-v-17d40f1c]{color:gray;font-size:16px}#result a[data-v-17d40f1c]{font-size:18px;color:#00f}#result p[data-v-17d40f1c]{margin:2px}#small_url_content[data-v-17d40f1c]{display:inline-block}#date[data-v-17d40f1c]{display:inline-block;font-size:12px;color:#666}#result li a[data-v-17d40f1c]{display:block;width:15em;word-break:keep-all;white-space:nowrap;overflow:hidden;text-overflow:ellipsis;font-size:12px;text-decoration:none;color:#008b00}#footer[data-v-17d40f1c]{position:relative;left:15%}#footer button[data-v-17d40f1c]{margin-right:20px;font-size:15px;background-color:#fff;border:1px solid #fff;padding:10px 14px;//border:none;color:#191970}#footer button[data-v-17d40f1c]:hover{border:1px solid #39f;cursor:hand} -------------------------------------------------------------------------------- /dist/static/css/app.bc6bcebd8dff1469ed2a180d243d1fb1.css.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///./src/components/searchEngine.vue","webpack:///./src/components/searchResult.vue"],"names":[],"mappings":"AACA,+BACI,SACA,QACA,WACA,eACA,UACA,qBAAuB,CAE3B,uBACI,UACA,YAEA,qBACA,mBACA,sBACA,eACA,UACA,eAAoB,CAExB,yBACI,cACA,YACA,SACA,sBACA,iBACA,mBACA,eACA,WACA,qBACA,SAAa,CC7BjB,6BACC,SAAW,CAEZ,+BACC,WACA,YACA,SACA,SAAW,CAEZ,yBACI,aACA,UACA,WACA,YACA,sBACA,eACA,MACA,OACA,SAAW,CAEf,wBACC,YACG,YACA,sBAGA,eACA,kBACA,SACA,OAAS,CAEb,yBACC,YACG,YACA,sBACA,YACA,qBACA,eACA,WACA,gBACA,oBACA,kBACA,QACA,QAAU,CAEd,yBACI,YACA,UACA,gBACA,kBACA,QAAU,CAEd,gCACC,WACA,cAAgB,CAEjB,2BACI,eACA,UAAe,CAEnB,2BACI,UAAW,CAOf,oCACC,oBAAsB,CAEvB,uBACC,qBACG,eACA,UAAe,CAEnB,8BACC,cACG,WACA,oBACA,mBACA,gBACA,uBACA,eACA,qBACA,aAAe,CAEnB,yBACC,kBACA,QAAU,CAEX,gCACC,kBACA,eACA,sBACA,sBACA,kBACA,cACA,aAAe,CAEhB,sCACC,sBACA,WAAa","file":"static/css/app.bc6bcebd8dff1469ed2a180d243d1fb1.css","sourcesContent":["\n#searchEngine[data-v-e082b27e]{\n left: 30%;\n top: 40%;\n width: 100%;\n position: fixed;\n z-index: 1;\n background-color: #FFF;\n}\n#text[data-v-e082b27e]{\n width: 30%;\n height: 41px;\n \n //border-style:solid;\n //border-width:1px;\n border: solid 1px #39F;\n font-size:24px;\n padding: 0px;\n margin:-1px 0 0 0px;\n}\n#button[data-v-e082b27e]{\n //float: right;\n height:45px;\n width:7%;\n background-color:#39F;\n border-width: 1px;\n border-style: solid;\n font-size:24px;\n color:#FFF;\n margin:-2px 0 0 -5px;\n padding: 0px;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/searchEngine.vue","\n.hightLight[data-v-17d40f1c]{\n\tcolor: red;\n}\n#searchResult[data-v-17d40f1c]{\n\twidth: 100%;\n\theight: 100%;\n\tmargin: 0;\n\tpadding: 0;\n}\n#header[data-v-17d40f1c]{\n margin-top: 0;\n padding: 0;\n width: 100%;\n height: 80px;\n background-color: #FFF;\n position: fixed;\n top: 0px;\n left: 0px;\n z-index: 1;\n}\n#input[data-v-17d40f1c]{\n\twidth: 600px;\n height: 35px;\n //border-color:#39F;\n border-style:solid;\n border-width:1px;\n font-size:24px;\n position: relative;\n left: 15%;\n top: 8px;\n}\n#submit[data-v-17d40f1c]{\n\theight:40px;\n width:120px;\n background-color:#39F;\n border:none;\n //border-style:solid;\n font-size:24px;\n color:#FFF;\n margin-top: -1px;\n //margin-left:-10px;\n position: relative;\n top: 8px;\n left: 10%;\n}\n#result[data-v-17d40f1c]{\n height: auto;\n width: 40%;\n margin-top: 80px;\n position: relative;\n left: 15%;\n}\n#result_number[data-v-17d40f1c]{\n\tcolor: gray;\n\tfont-size: 16px;\n}\n#result a[data-v-17d40f1c]{\n font-size: 18px;\n color: #0000FF;\n}\n#result p[data-v-17d40f1c]{\n margin:2px;\n}\n/*#result li{\n display: inline-block;\n font-size: 12px;\n color: #666666;\n}*/\n#small_url_content[data-v-17d40f1c]{\n\tdisplay: inline-block;\n}\n#date[data-v-17d40f1c]{\n\tdisplay: inline-block;\n font-size: 12px;\n color: #666666;\n}\n#result li a[data-v-17d40f1c]{\n\tdisplay:block;/*内联对象需加*/\n width:15em;\n word-break:keep-all;/* 不换行 */\n white-space:nowrap;/* 不换行 */\n overflow:hidden;/* 内容超出宽度时隐藏超出部分的内容 */\n text-overflow:ellipsis;/* 当对象内文本溢出时显示省略标记(...) ;需与overflow:hidden;一起使用。*/\n font-size: 12px;\n text-decoration: none;\n color: #008B00;\n}\n#footer[data-v-17d40f1c]{\n\tposition: relative;\n\tleft: 15%;\n}\n#footer button[data-v-17d40f1c]{\n\tmargin-right:20px;\n\tfont-size: 15px;\n\tbackground-color: #FFF;\n\tborder:solid 1px #FFF;\n\tpadding: 10px 14px 10px 14px;\n\t//border:none;\n\tcolor: #191970;\n}\n#footer button[data-v-17d40f1c]:hover{\n\tborder:solid 1px #39F;\n\tcursor: hand;\n}\n\n\n\n// WEBPACK FOOTER //\n// ./src/components/searchResult.vue"],"sourceRoot":""} -------------------------------------------------------------------------------- /dist/static/js/app.2e2f3fd3b6a1a7409115.js: -------------------------------------------------------------------------------- 1 | webpackJsonp([1],[,,,,,,,,,,,,,function(t,e,n){"use strict";var r=n(3),s=n(55),i=n(50),a=n.n(i),o=n(51),u=n.n(o);r.a.use(s.a),e.a=new s.a({routes:[{path:"/",name:"searchEngine",component:a.a},{path:"/result",name:"searchResult",component:u.a}]})},function(t,e,n){n(42);var r=n(2)(n(32),n(53),null,null);t.exports=r.exports},,,,,,,,,,,,,,,,,,function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={name:"app",data:function(){return{query:""}},methods:{showResult:function(t){this.query=t,console.log(this.query),this.$router.replace({path:"/result"})}}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0}),e.default={name:"searchEngine",data:function(){return{query:""}},methods:{change:function(){this.$emit("childChange",this.query)},submit:function(){location.reload()}}}},function(t,e,n){"use strict";Object.defineProperty(e,"__esModule",{value:!0});var r=n(36),s=n.n(r);e.default={name:"searchResult",props:["parentQuery"],mounted:function(){document.getElementById("input").focus()},updated:function(){if(""!=this.query){var t,e=(this.query.split(""),document.getElementsByClassName("item_description")),n=document.getElementsByClassName("item_title"),r=new RegExp(this.query,"g");for(t in e){var s=e[t].innerHTML,i=n[t].innerHTML;i=i.replace(r,""+this.query+""),s=s.replace(r,""+this.query+""),e[t].innerHTML=s,n[t].innerHTML=i}}},data:function(){return{msg:"Welcome to Your Vue.js App",query:this.parentQuery,page_select:1,tips:"请输入要搜索的内容",show_button:!1,response:[]}},computed:{length:function(){var t=0;for(var e in this.response)t++;return t},part_response:function(){for(var t=[],e=10*(this.page_select-1);e<10*this.page_select;e++)e",components:{App:i.a}})},,,,,,function(t,e){},function(t,e){},function(t,e){},,,,,,,function(t,e,n){n(43);var r=n(2)(n(33),n(54),"data-v-e082b27e",null);t.exports=r.exports},function(t,e,n){n(41);var r=n(2)(n(34),n(52),"data-v-17d40f1c",null);t.exports=r.exports},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{attrs:{id:"searchResult"}},[n("div",{attrs:{id:"header"}},[n("input",{directives:[{name:"model",rawName:"v-model",value:t.query,expression:"query"}],attrs:{type:"text",id:"input"},domProps:{value:t.query},on:{keyup:function(e){if(!("button"in e)&&t._k(e.keyCode,"enter",13))return null;t.submit(e)},input:function(e){e.target.composing||(t.query=e.target.value)}}}),t._v(" "),n("button",{attrs:{id:"submit"},on:{click:t.submit}},[t._v("search")])]),t._v(" "),n("div",{attrs:{id:"result"}},[n("p",{attrs:{id:"result_number"}},[t._v(t._s(t.tips))]),t._v(" "),t._l(t.part_response,function(e){return n("div",[n("a",{staticClass:"item_title",attrs:{id:"title",href:e.url,target:"_blank"}},[t._v(t._s(e.title))]),t._v(" "),n("p",{staticClass:"item_description"},[t._v(t._s(e.description))]),t._v(" "),n("li",{attrs:{id:"small_url_content"}},[n("a",{attrs:{href:e.url,id:"small_url",target:"_blank"}},[t._v(t._s(e.url))])]),t._v(" "),n("li",{attrs:{id:"date"}},[t._v(" "+t._s(e.date))])])})],2),t._v(" "),n("div",{attrs:{id:"footer"}},t._l(parseInt(t.length/10)+1,function(e){return t.show_button?n("button",{on:{click:function(n){t.page_select=e}}},[t._v(t._s(e))]):t._e()}))])},staticRenderFns:[]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{attrs:{id:"app"}},[n("router-view",{attrs:{"parent-query":t.query},on:{childChange:t.showResult}})],1)},staticRenderFns:[]}},function(t,e){t.exports={render:function(){var t=this,e=t.$createElement,n=t._self._c||e;return n("div",{attrs:{id:"searchEngine"}},[n("input",{directives:[{name:"model",rawName:"v-model",value:t.query,expression:"query"}],attrs:{type:"text",id:"text"},domProps:{value:t.query},on:{input:[function(e){e.target.composing||(t.query=e.target.value)},t.change]}}),t._v(" "),n("button",{attrs:{id:"button"},on:{click:t.submit}},[t._v("search")])])},staticRenderFns:[]}}],[35]); 2 | //# sourceMappingURL=app.2e2f3fd3b6a1a7409115.js.map -------------------------------------------------------------------------------- /dist/static/js/app.2e2f3fd3b6a1a7409115.js.map: -------------------------------------------------------------------------------- 1 | {"version":3,"sources":["webpack:///static/js/app.2e2f3fd3b6a1a7409115.js","webpack:///./src/router/index.js","webpack:///./src/App.vue","webpack:///App.vue","webpack:///searchEngine.vue","webpack:///searchResult.vue","webpack:///./src/main.js","webpack:///./src/components/searchEngine.vue?297e","webpack:///./src/components/searchResult.vue?72a3","webpack:///./src/components/searchResult.vue?cd92","webpack:///./src/App.vue?0d65","webpack:///./src/components/searchEngine.vue?0821"],"names":["webpackJsonp","module","__webpack_exports__","__webpack_require__","__WEBPACK_IMPORTED_MODULE_0_vue__","__WEBPACK_IMPORTED_MODULE_1_vue_router__","__WEBPACK_IMPORTED_MODULE_2__components_searchEngine__","__WEBPACK_IMPORTED_MODULE_2__components_searchEngine___default","n","__WEBPACK_IMPORTED_MODULE_3__components_searchResult__","__WEBPACK_IMPORTED_MODULE_3__components_searchResult___default","use","routes","path","name","component","a","exports","Component","Object","defineProperty","value","data","query","methods","showResult","this","console","log","$router","replace","change","$emit","submit","location","reload","__WEBPACK_IMPORTED_MODULE_0_babel_runtime_core_js_json_stringify__","__WEBPACK_IMPORTED_MODULE_0_babel_runtime_core_js_json_stringify___default","props","mounted","document","getElementById","focus","updated","index","item_description","split","getElementsByClassName","item_title","re","RegExp","description_text","innerHTML","title_text","msg","parentQuery","page_select","tips","show_button","response","computed","length","len","item","part_response","part","start","push","split_query","_this","qs","$axios","post","stringify","question","then","catch","error","__WEBPACK_IMPORTED_MODULE_1__App__","__WEBPACK_IMPORTED_MODULE_1__App___default","__WEBPACK_IMPORTED_MODULE_2__router__","__WEBPACK_IMPORTED_MODULE_3_axios__","__WEBPACK_IMPORTED_MODULE_3_axios___default","defaults","headers","prototype","config","productionTip","el","router","template","components","App","render","_vm","_h","$createElement","_c","_self","attrs","id","directives","rawName","expression","type","domProps","on","keyup","$event","_k","keyCode","input","target","composing","_v","click","_s","_l","staticClass","href","url","title","description","date","parseInt","_e","staticRenderFns","parent-query","childChange"],"mappings":"AAAAA,cAAc,IACP,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACC,CACA,CACA,CAEF,SAAUC,EAAQC,EAAqBC,GAE7C,YACqB,IAAIC,GAAoCD,EAAoB,GACxDE,EAA2CF,EAAoB,IAC/DG,EAAyDH,EAAoB,IAC7EI,EAAiEJ,EAAoBK,EAAEF,GACvFG,EAAyDN,EAAoB,IAC7EO,EAAiEP,EAAoBK,EAAEC,EClBhHL,GAAA,EAAIO,IAAIN,EAAA,GAERH,EAAA,KAAmBG,GAAA,GACjBO,SAEIC,KAAM,IACNC,KAAM,eACNC,UAAWR,EAAAS,IAGXH,KAAM,UACNC,KAAM,eACNC,UAAWL,EAAAM,OD4BX,SAAUf,EAAQgB,EAASd,GE3CjCA,EAAA,GAEA,IAAAe,GAAAf,EAAA,GAEAA,EAAA,IAEAA,EAAA,IAEA,KAEA,KAGAF,GAAAgB,QAAAC,EAAAD,SFmDQ,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CACA,CAEF,SAAUhB,EAAQC,EAAqBC,GAE7C,YACAgB,QAAOC,eAAelB,EAAqB,cAAgBmB,OAAO,IGhFlEnB,EAAA,SHoFEY,KGlFF,MHmFEQ,KAAM,WACJ,OACEC,MGjFN,KHqFEC,SACEC,WAAY,SAAoBH,GAC9BI,KAAKH,MGlFXD,EHmFMK,QAAQC,IAAIF,KGlFlBH,OHmFMG,KAAKG,QAAQC,SAAUjB,KGlF7B,gBHyFM,SAAUZ,EAAQC,EAAqBC,GAE7C,YACAgB,QAAOC,eAAelB,EAAqB,cAAgBmB,OAAO,IIxGlEnB,EAAA,SJ4GEY,KI1GF,eJ2GEQ,KAAM,WACJ,OACEC,MIxGN,KJ6GEC,SACEO,OAAQ,WACNL,KAAKM,MAAM,cAAeN,KI3GhCH,QJ6GIU,OAAQ,WACNC,SI3GNC,aJkHM,SAAUlC,EAAQC,EAAqBC,GAE7C,YACAgB,QAAOC,eAAelB,EAAqB,cAAgBmB,OAAO,GAC7C,IAAIe,GAAqEjC,EAAoB,IACzFkC,EAA6ElC,EAAoBK,EAAE4B,EKvH5HlC,GAAA,SL4HEY,KK1HF,eL2HEwB,OK1HF,eL2HEC,QAAS,WACWC,SAASC,eK1H/B,SACAC,SL4HEC,QAAS,WACP,GAAkB,IAAdjB,KAAKH,MK1Hb,CL2HM,GKtHNqB,GLuHUC,GADcnB,KAAKH,MAAMuB,MK1HnC,IL2H6BN,SAASO,uBK1HtC,qBL2HUC,EAAaR,SAASO,uBK1HhC,cL2HUE,EAAK,GAAIC,QAAOxB,KAAKH,MK1H/B,IL4HM,KAAKqB,IAASC,GK1HpB,CL2HQ,GAAIM,GAAmBN,EAAiBD,GK1HhDQ,UL2HYC,EAAaL,EAAWJ,GK1HpCQ,SL2HQC,GAAaA,EAAWvB,QAAQmB,EAAI,2BAA6BvB,KAAKH,MK1H9E,WL2HQ4B,EAAmBA,EAAiBrB,QAAQmB,EAAI,2BAA6BvB,KAAKH,MK1H1F,WL2HQsB,EAAiBD,GAAOQ,UK1HhCD,EL2HQH,EAAWJ,GAAOQ,UK1H1BC,KL8HE/B,KAAM,WACJ,OACEgC,IKxHN,6BLyHM/B,MAAOG,KKvHb6B,YLyHMC,YKxHN,ELyHMC,KKxHN,YLyHMC,aKxHN,ELyHMC,cAIJC,UACEC,OAAQ,WACN,GAAIC,GKtHV,CLuHM,KAAK,GAAIC,KAAQrC,MAAKiC,SKrH5BG,GLwHM,OKtHNA,ILwHIE,cAAe,WAEb,IAAK,GADDC,MACKC,EAAiC,IAAxBxC,KAAK8B,YAAc,GAASU,EAA2B,GAAnBxC,KAAK8B,YAAkBU,IACvEA,EAAQxC,KAAKmC,QACfI,EAAKE,KAAKzC,KAAKiC,SKtHzBO,GL0HM,IAAIE,GAAc1C,KAAKH,MAAMuB,MKtHnC,GLuHMnB,SAAQC,IKtHdwC,ELwHwB/B,KK7GxB4B,EL+GM,OK9GNA,KLiHEzC,SACES,OAAQ,WK9GZ,GAAAoC,GAAA3C,ILiHMA,MAAK+B,KKhHX,SLiHM,IAAIa,GAAKnE,EK/Gf,GLiHMuB,MAAK6C,OAAOC,KKhHlB,iBAAAF,EAAAG,WLiHQC,SAAYhD,KK/GpBH,SADAoD,KAAA,SAAAhB,GLkHQU,EAAMX,aK/Gd,ELgHQW,EAAMV,SAAWA,EK9GzBrC,KLgHQ+C,EAAMZ,KAAO,SAAWY,EAAMR,OK/GtC,QACAe,MAAA,SAAAC,GLgHQR,EAAMZ,KK9Gd,eL+GQ9B,QAAQC,IK9GhBiD,SLsHM,SAAU5E,EAAQC,EAAqBC,GAE7C,YACAgB,QAAOC,eAAelB,EAAqB,cAAgBmB,OAAO,GAC7C,IAAIjB,GAAoCD,EAAoB,GACxD2E,EAAqC3E,EAAoB,IACzD4E,EAA6C5E,EAAoBK,EAAEsE,GACnEE,EAAwC7E,EAAoB,IAC5D8E,EAAsC9E,EAAoB,IAC1D+E,EAA8C/E,EAAoBK,EAAEyE,EMxO7FC,GAAAlE,EAAMmE,SAASC,QAAQZ,KAAK,gBAAkB,oCAC9CpE,EAAA,EAAIiF,UAAUd,OAASW,EAAAlE,EAEvBZ,EAAA,EAAIkF,OAAOC,eAAgB,EAG3B,GAAInF,GAAA,GACFoF,GAAI,OACJC,OAAAT,EAAA,EACAU,SAAU,SACVC,YAAcC,IAAAb,EAAA/D,MNiPR,CACA,CACA,CACA,CACA,CAEF,SAAUf,EAAQgB,KAMlB,SAAUhB,EAAQgB,KAMlB,SAAUhB,EAAQgB,KAKhB,CACA,CACA,CACA,CACA,CACA,CAEF,SAAUhB,EAAQgB,EAASd,GO7RjCA,EAAA,GAEA,IAAAe,GAAAf,EAAA,GAEAA,EAAA,IAEAA,EAAA,IAEA,kBAEA,KAGAF,GAAAgB,QAAAC,EAAAD,SPsSM,SAAUhB,EAAQgB,EAASd,GQnTjCA,EAAA,GAEA,IAAAe,GAAAf,EAAA,GAEAA,EAAA,IAEAA,EAAA,IAEA,kBAEA,KAGAF,GAAAgB,QAAAC,EAAAD,SR4TM,SAAUhB,EAAQgB,GS3UxBhB,EAAAgB,SAAgB4E,OAAA,WAAmB,GAAAC,GAAApE,KAAaqE,EAAAD,EAAAE,eAA0BC,EAAAH,EAAAI,MAAAD,IAAAF,CAC1E,OAAAE,GAAA,OACAE,OACAC,GAAA,kBAEGH,EAAA,OACHE,OACAC,GAAA,YAEGH,EAAA,SACHI,aACAvF,KAAA,QACAwF,QAAA,UACAjF,MAAAyE,EAAA,MACAS,WAAA,UAEAJ,OACAK,KAAA,OACAJ,GAAA,SAEAK,UACApF,MAAAyE,EAAA,OAEAY,IACAC,MAAA,SAAAC,GACA,eAAAA,KAAAd,EAAAe,GAAAD,EAAAE,QAAA,YAA2E,WAC3EhB,GAAA7D,OAAA2E,IAEAG,MAAA,SAAAH,GACAA,EAAAI,OAAAC,YACAnB,EAAAvE,MAAAqF,EAAAI,OAAA3F,WAGGyE,EAAAoB,GAAA,KAAAjB,EAAA,UACHE,OACAC,GAAA,UAEAM,IACAS,MAAArB,EAAA7D,UAEG6D,EAAAoB,GAAA,cAAApB,EAAAoB,GAAA,KAAAjB,EAAA,OACHE,OACAC,GAAA,YAEGH,EAAA,KACHE,OACAC,GAAA,mBAEGN,EAAAoB,GAAApB,EAAAsB,GAAAtB,EAAArC,SAAAqC,EAAAoB,GAAA,KAAApB,EAAAuB,GAAAvB,EAAA,uBAAA/B,GACH,MAAAkC,GAAA,OAAAA,EAAA,KACAqB,YAAA,aACAnB,OACAC,GAAA,QACAmB,KAAAxD,EAAAyD,IACAR,OAAA,YAEKlB,EAAAoB,GAAApB,EAAAsB,GAAArD,EAAA0D,UAAA3B,EAAAoB,GAAA,KAAAjB,EAAA,KACLqB,YAAA,qBACKxB,EAAAoB,GAAApB,EAAAsB,GAAArD,EAAA2D,gBAAA5B,EAAAoB,GAAA,KAAAjB,EAAA,MACLE,OACAC,GAAA,uBAEKH,EAAA,KACLE,OACAoB,KAAAxD,EAAAyD,IACApB,GAAA,YACAY,OAAA,YAEKlB,EAAAoB,GAAApB,EAAAsB,GAAArD,EAAAyD,UAAA1B,EAAAoB,GAAA,KAAAjB,EAAA,MACLE,OACAC,GAAA,UAEKN,EAAAoB,GAAA,IAAApB,EAAAsB,GAAArD,EAAA4D,cACF,GAAA7B,EAAAoB,GAAA,KAAAjB,EAAA,OACHE,OACAC,GAAA,WAEGN,EAAAuB,GAAAO,SAAA9B,EAAAjC,OAAA,eAAArD,GACH,MAAAsF,GAAA,YAAAG,EAAA,UACAS,IACAS,MAAA,SAAAP,GACAd,EAAAtC,YAAAhD,MAGKsF,EAAAoB,GAAApB,EAAAsB,GAAA5G,MAAAsF,EAAA+B,WAEJC,qBTiVK,SAAU7H,EAAQgB,GUvaxBhB,EAAAgB,SAAgB4E,OAAA,WAAmB,GAAAC,GAAApE,KAAaqE,EAAAD,EAAAE,eAA0BC,EAAAH,EAAAI,MAAAD,IAAAF,CAC1E,OAAAE,GAAA,OACAE,OACAC,GAAA,SAEGH,EAAA,eACHE,OACA4B,eAAAjC,EAAAvE,OAEAmF,IACAsB,YAAAlC,EAAArE,eAEG,IACFqG,qBV6aK,SAAU7H,EAAQgB,GW1bxBhB,EAAAgB,SAAgB4E,OAAA,WAAmB,GAAAC,GAAApE,KAAaqE,EAAAD,EAAAE,eAA0BC,EAAAH,EAAAI,MAAAD,IAAAF,CAC1E,OAAAE,GAAA,OACAE,OACAC,GAAA,kBAEGH,EAAA,SACHI,aACAvF,KAAA,QACAwF,QAAA,UACAjF,MAAAyE,EAAA,MACAS,WAAA,UAEAJ,OACAK,KAAA,OACAJ,GAAA,QAEAK,UACApF,MAAAyE,EAAA,OAEAY,IACAK,OAAA,SAAAH,GACAA,EAAAI,OAAAC,YACAnB,EAAAvE,MAAAqF,EAAAI,OAAA3F,QACOyE,EAAA/D,WAEJ+D,EAAAoB,GAAA,KAAAjB,EAAA,UACHE,OACAC,GAAA,UAEAM,IACAS,MAAArB,EAAA7D,UAEG6D,EAAAoB,GAAA,eACFY,uBX+bE","file":"static/js/app.2e2f3fd3b6a1a7409115.js","sourcesContent":["webpackJsonp([1],[\n/* 0 */,\n/* 1 */,\n/* 2 */,\n/* 3 */,\n/* 4 */,\n/* 5 */,\n/* 6 */,\n/* 7 */,\n/* 8 */,\n/* 9 */,\n/* 10 */,\n/* 11 */,\n/* 12 */,\n/* 13 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_vue__ = __webpack_require__(3);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1_vue_router__ = __webpack_require__(55);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__components_searchEngine__ = __webpack_require__(50);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__components_searchEngine___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_2__components_searchEngine__);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__components_searchResult__ = __webpack_require__(51);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3__components_searchResult___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3__components_searchResult__);\n\n\n\n\n\n__WEBPACK_IMPORTED_MODULE_0_vue__[\"a\" /* default */].use(__WEBPACK_IMPORTED_MODULE_1_vue_router__[\"a\" /* default */]);\n\n/* harmony default export */ __webpack_exports__[\"a\"] = (new __WEBPACK_IMPORTED_MODULE_1_vue_router__[\"a\" /* default */]({\n routes: [{\n path: '/',\n name: 'searchEngine',\n component: __WEBPACK_IMPORTED_MODULE_2__components_searchEngine___default.a\n }, {\n path: '/result',\n name: 'searchResult',\n component: __WEBPACK_IMPORTED_MODULE_3__components_searchResult___default.a\n }]\n}));\n\n/***/ }),\n/* 14 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\n/* styles */\n__webpack_require__(42)\n\nvar Component = __webpack_require__(2)(\n /* script */\n __webpack_require__(32),\n /* template */\n __webpack_require__(53),\n /* scopeId */\n null,\n /* cssModules */\n null\n)\n\nmodule.exports = Component.exports\n\n\n/***/ }),\n/* 15 */,\n/* 16 */,\n/* 17 */,\n/* 18 */,\n/* 19 */,\n/* 20 */,\n/* 21 */,\n/* 22 */,\n/* 23 */,\n/* 24 */,\n/* 25 */,\n/* 26 */,\n/* 27 */,\n/* 28 */,\n/* 29 */,\n/* 30 */,\n/* 31 */,\n/* 32 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: 'app',\n data: function data() {\n return {\n query: ''\n };\n },\n\n methods: {\n showResult: function showResult(data) {\n this.query = data;\n console.log(this.query);\n this.$router.replace({ path: '/result' });\n }\n }\n});\n\n/***/ }),\n/* 33 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: 'searchEngine',\n data: function data() {\n return {\n query: ''\n\n };\n },\n\n methods: {\n change: function change() {\n this.$emit('childChange', this.query);\n },\n submit: function submit() {\n location.reload();\n }\n }\n});\n\n/***/ }),\n/* 34 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_babel_runtime_core_js_json_stringify__ = __webpack_require__(36);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_babel_runtime_core_js_json_stringify___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_0_babel_runtime_core_js_json_stringify__);\n\n\n\n/* harmony default export */ __webpack_exports__[\"default\"] = ({\n name: 'searchResult',\n props: ['parentQuery'],\n mounted: function mounted() {\n var input_query = document.getElementById('input');\n input_query.focus();\n },\n updated: function updated() {\n if (this.query != \"\") {\n var split_query = this.query.split(\"\");\n var item_description = document.getElementsByClassName('item_description');\n var item_title = document.getElementsByClassName('item_title');\n var re = new RegExp(this.query, \"g\");\n var index;\n for (index in item_description) {\n var description_text = item_description[index].innerHTML;\n var title_text = item_title[index].innerHTML;\n title_text = title_text.replace(re, \"\" + this.query + \"\");\n description_text = description_text.replace(re, \"\" + this.query + \"\");\n item_description[index].innerHTML = description_text;\n item_title[index].innerHTML = title_text;\n }\n }\n },\n data: function data() {\n return {\n msg: 'Welcome to Your Vue.js App',\n query: this.parentQuery,\n\n page_select: 1,\n tips: '请输入要搜索的内容',\n show_button: false,\n response: []\n };\n },\n\n computed: {\n length: function length() {\n var len = 0;\n for (var item in this.response) {\n len++;\n }\n return len;\n },\n part_response: function part_response() {\n var part = [];\n for (var start = (this.page_select - 1) * 10; start < this.page_select * 10; start++) {\n if (start < this.length) {\n part.push(this.response[start]);\n }\n }\n\n var split_query = this.query.split(\"\");\n console.log(split_query);\n var char;\n var part_to_str = __WEBPACK_IMPORTED_MODULE_0_babel_runtime_core_js_json_stringify___default()(part);\n\n return part;\n }\n },\n methods: {\n submit: function submit() {\n var _this = this;\n\n this.tips = '正在查询。。。';\n var qs = __webpack_require__(47);\n\n this.$axios.post('./back_end.php', qs.stringify({\n 'question': this.query\n })).then(function (response) {\n _this.show_button = true;\n _this.response = response.data;\n\n _this.tips = '为您找到大约' + _this.length + '个结果';\n }).catch(function (error) {\n _this.tips = '查询失败,请检查网络连接';\n console.log(error);\n });\n }\n }\n});\n\n/***/ }),\n/* 35 */\n/***/ (function(module, __webpack_exports__, __webpack_require__) {\n\n\"use strict\";\nObject.defineProperty(__webpack_exports__, \"__esModule\", { value: true });\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_0_vue__ = __webpack_require__(3);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__App__ = __webpack_require__(14);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_1__App___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_1__App__);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_2__router__ = __webpack_require__(13);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_axios__ = __webpack_require__(12);\n/* harmony import */ var __WEBPACK_IMPORTED_MODULE_3_axios___default = __webpack_require__.n(__WEBPACK_IMPORTED_MODULE_3_axios__);\n\n\n\n\n\n__WEBPACK_IMPORTED_MODULE_3_axios___default.a.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';\n__WEBPACK_IMPORTED_MODULE_0_vue__[\"a\" /* default */].prototype.$axios = __WEBPACK_IMPORTED_MODULE_3_axios___default.a;\n\n__WEBPACK_IMPORTED_MODULE_0_vue__[\"a\" /* default */].config.productionTip = false;\n\nnew __WEBPACK_IMPORTED_MODULE_0_vue__[\"a\" /* default */]({\n el: '#app',\n router: __WEBPACK_IMPORTED_MODULE_2__router__[\"a\" /* default */],\n template: '',\n components: { App: __WEBPACK_IMPORTED_MODULE_1__App___default.a }\n});\n\n/***/ }),\n/* 36 */,\n/* 37 */,\n/* 38 */,\n/* 39 */,\n/* 40 */,\n/* 41 */\n/***/ (function(module, exports) {\n\n// removed by extract-text-webpack-plugin\n\n/***/ }),\n/* 42 */\n/***/ (function(module, exports) {\n\n// removed by extract-text-webpack-plugin\n\n/***/ }),\n/* 43 */\n/***/ (function(module, exports) {\n\n// removed by extract-text-webpack-plugin\n\n/***/ }),\n/* 44 */,\n/* 45 */,\n/* 46 */,\n/* 47 */,\n/* 48 */,\n/* 49 */,\n/* 50 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\n/* styles */\n__webpack_require__(43)\n\nvar Component = __webpack_require__(2)(\n /* script */\n __webpack_require__(33),\n /* template */\n __webpack_require__(54),\n /* scopeId */\n \"data-v-e082b27e\",\n /* cssModules */\n null\n)\n\nmodule.exports = Component.exports\n\n\n/***/ }),\n/* 51 */\n/***/ (function(module, exports, __webpack_require__) {\n\n\n/* styles */\n__webpack_require__(41)\n\nvar Component = __webpack_require__(2)(\n /* script */\n __webpack_require__(34),\n /* template */\n __webpack_require__(52),\n /* scopeId */\n \"data-v-17d40f1c\",\n /* cssModules */\n null\n)\n\nmodule.exports = Component.exports\n\n\n/***/ }),\n/* 52 */\n/***/ (function(module, exports) {\n\nmodule.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;\n return _c('div', {\n attrs: {\n \"id\": \"searchResult\"\n }\n }, [_c('div', {\n attrs: {\n \"id\": \"header\"\n }\n }, [_c('input', {\n directives: [{\n name: \"model\",\n rawName: \"v-model\",\n value: (_vm.query),\n expression: \"query\"\n }],\n attrs: {\n \"type\": \"text\",\n \"id\": \"input\"\n },\n domProps: {\n \"value\": (_vm.query)\n },\n on: {\n \"keyup\": function($event) {\n if (!('button' in $event) && _vm._k($event.keyCode, \"enter\", 13)) { return null; }\n _vm.submit($event)\n },\n \"input\": function($event) {\n if ($event.target.composing) { return; }\n _vm.query = $event.target.value\n }\n }\n }), _vm._v(\" \"), _c('button', {\n attrs: {\n \"id\": \"submit\"\n },\n on: {\n \"click\": _vm.submit\n }\n }, [_vm._v(\"search\")])]), _vm._v(\" \"), _c('div', {\n attrs: {\n \"id\": \"result\"\n }\n }, [_c('p', {\n attrs: {\n \"id\": \"result_number\"\n }\n }, [_vm._v(_vm._s(_vm.tips))]), _vm._v(\" \"), _vm._l((_vm.part_response), function(item) {\n return _c('div', [_c('a', {\n staticClass: \"item_title\",\n attrs: {\n \"id\": \"title\",\n \"href\": item.url,\n \"target\": \"_blank\"\n }\n }, [_vm._v(_vm._s(item.title))]), _vm._v(\" \"), _c('p', {\n staticClass: \"item_description\"\n }, [_vm._v(_vm._s(item.description))]), _vm._v(\" \"), _c('li', {\n attrs: {\n \"id\": \"small_url_content\"\n }\n }, [_c('a', {\n attrs: {\n \"href\": item.url,\n \"id\": \"small_url\",\n \"target\": \"_blank\"\n }\n }, [_vm._v(_vm._s(item.url))])]), _vm._v(\" \"), _c('li', {\n attrs: {\n \"id\": \"date\"\n }\n }, [_vm._v(\" \" + _vm._s(item.date))])])\n })], 2), _vm._v(\" \"), _c('div', {\n attrs: {\n \"id\": \"footer\"\n }\n }, _vm._l((parseInt(_vm.length / 10) + 1), function(n) {\n return (_vm.show_button) ? _c('button', {\n on: {\n \"click\": function($event) {\n _vm.page_select = n\n }\n }\n }, [_vm._v(_vm._s(n))]) : _vm._e()\n }))])\n},staticRenderFns: []}\n\n/***/ }),\n/* 53 */\n/***/ (function(module, exports) {\n\nmodule.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;\n return _c('div', {\n attrs: {\n \"id\": \"app\"\n }\n }, [_c('router-view', {\n attrs: {\n \"parent-query\": _vm.query\n },\n on: {\n \"childChange\": _vm.showResult\n }\n })], 1)\n},staticRenderFns: []}\n\n/***/ }),\n/* 54 */\n/***/ (function(module, exports) {\n\nmodule.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;\n return _c('div', {\n attrs: {\n \"id\": \"searchEngine\"\n }\n }, [_c('input', {\n directives: [{\n name: \"model\",\n rawName: \"v-model\",\n value: (_vm.query),\n expression: \"query\"\n }],\n attrs: {\n \"type\": \"text\",\n \"id\": \"text\"\n },\n domProps: {\n \"value\": (_vm.query)\n },\n on: {\n \"input\": [function($event) {\n if ($event.target.composing) { return; }\n _vm.query = $event.target.value\n }, _vm.change]\n }\n }), _vm._v(\" \"), _c('button', {\n attrs: {\n \"id\": \"button\"\n },\n on: {\n \"click\": _vm.submit\n }\n }, [_vm._v(\"search\")])])\n},staticRenderFns: []}\n\n/***/ })\n],[35]);\n\n\n// WEBPACK FOOTER //\n// static/js/app.2e2f3fd3b6a1a7409115.js","import Vue from 'vue'\nimport Router from 'vue-router'\nimport searchEngine from '@/components/searchEngine'\nimport searchResult from '@/components/searchResult'\n\nVue.use(Router)\n\nexport default new Router({\n routes: [\n {\n path: '/',\n name: 'searchEngine',\n component: searchEngine\n },\n {\n path: '/result',\n name: 'searchResult',\n component: searchResult\n }\n ]\n})\n\n\n\n// WEBPACK FOOTER //\n// ./src/router/index.js","\n/* styles */\nrequire(\"!!../node_modules/extract-text-webpack-plugin/loader.js?{\\\"omit\\\":1,\\\"remove\\\":true}!vue-style-loader!css-loader?{\\\"minimize\\\":true,\\\"sourceMap\\\":true}!../node_modules/vue-loader/lib/style-compiler/index?{\\\"id\\\":\\\"data-v-3368385f\\\",\\\"scoped\\\":false,\\\"hasInlineConfig\\\":false}!../node_modules/vue-loader/lib/selector?type=styles&index=0!./App.vue\")\n\nvar Component = require(\"!../node_modules/vue-loader/lib/component-normalizer\")(\n /* script */\n require(\"!!babel-loader!../node_modules/vue-loader/lib/selector?type=script&index=0!./App.vue\"),\n /* template */\n require(\"!!../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-3368385f\\\"}!../node_modules/vue-loader/lib/selector?type=template&index=0!./App.vue\"),\n /* scopeId */\n null,\n /* cssModules */\n null\n)\n\nmodule.exports = Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/App.vue\n// module id = 14\n// module chunks = 1","\n\n\n\n\n\n\n\n// WEBPACK FOOTER //\n// App.vue?95b3cfb0","\n\n\n\n\n\n\n\n\n// WEBPACK FOOTER //\n// searchEngine.vue?6023da28","\n\n\n\n\n\n\n\n\n// WEBPACK FOOTER //\n// searchResult.vue?4a96ffc2","// The Vue build version to load with the `import` command\n// (runtime-only or standalone) has been set in webpack.base.conf with an alias.\nimport Vue from 'vue'\nimport App from './App'\nimport router from './router'\nimport axios from 'axios'\naxios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded';\nVue.prototype.$axios = axios\n\nVue.config.productionTip = false\n\n/* eslint-disable no-new */\nnew Vue({\n el: '#app',\n router,\n template: '',\n components: { App }\n})\n\n\n\n// WEBPACK FOOTER //\n// ./src/main.js","\n/* styles */\nrequire(\"!!../../node_modules/extract-text-webpack-plugin/loader.js?{\\\"omit\\\":1,\\\"remove\\\":true}!vue-style-loader!css-loader?{\\\"minimize\\\":true,\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index?{\\\"id\\\":\\\"data-v-e082b27e\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./searchEngine.vue\")\n\nvar Component = require(\"!../../node_modules/vue-loader/lib/component-normalizer\")(\n /* script */\n require(\"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./searchEngine.vue\"),\n /* template */\n require(\"!!../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-e082b27e\\\"}!../../node_modules/vue-loader/lib/selector?type=template&index=0!./searchEngine.vue\"),\n /* scopeId */\n \"data-v-e082b27e\",\n /* cssModules */\n null\n)\n\nmodule.exports = Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/searchEngine.vue\n// module id = 50\n// module chunks = 1","\n/* styles */\nrequire(\"!!../../node_modules/extract-text-webpack-plugin/loader.js?{\\\"omit\\\":1,\\\"remove\\\":true}!vue-style-loader!css-loader?{\\\"minimize\\\":true,\\\"sourceMap\\\":true}!../../node_modules/vue-loader/lib/style-compiler/index?{\\\"id\\\":\\\"data-v-17d40f1c\\\",\\\"scoped\\\":true,\\\"hasInlineConfig\\\":false}!../../node_modules/vue-loader/lib/selector?type=styles&index=0!./searchResult.vue\")\n\nvar Component = require(\"!../../node_modules/vue-loader/lib/component-normalizer\")(\n /* script */\n require(\"!!babel-loader!../../node_modules/vue-loader/lib/selector?type=script&index=0!./searchResult.vue\"),\n /* template */\n require(\"!!../../node_modules/vue-loader/lib/template-compiler/index?{\\\"id\\\":\\\"data-v-17d40f1c\\\"}!../../node_modules/vue-loader/lib/selector?type=template&index=0!./searchResult.vue\"),\n /* scopeId */\n \"data-v-17d40f1c\",\n /* cssModules */\n null\n)\n\nmodule.exports = Component.exports\n\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./src/components/searchResult.vue\n// module id = 51\n// module chunks = 1","module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;\n return _c('div', {\n attrs: {\n \"id\": \"searchResult\"\n }\n }, [_c('div', {\n attrs: {\n \"id\": \"header\"\n }\n }, [_c('input', {\n directives: [{\n name: \"model\",\n rawName: \"v-model\",\n value: (_vm.query),\n expression: \"query\"\n }],\n attrs: {\n \"type\": \"text\",\n \"id\": \"input\"\n },\n domProps: {\n \"value\": (_vm.query)\n },\n on: {\n \"keyup\": function($event) {\n if (!('button' in $event) && _vm._k($event.keyCode, \"enter\", 13)) { return null; }\n _vm.submit($event)\n },\n \"input\": function($event) {\n if ($event.target.composing) { return; }\n _vm.query = $event.target.value\n }\n }\n }), _vm._v(\" \"), _c('button', {\n attrs: {\n \"id\": \"submit\"\n },\n on: {\n \"click\": _vm.submit\n }\n }, [_vm._v(\"search\")])]), _vm._v(\" \"), _c('div', {\n attrs: {\n \"id\": \"result\"\n }\n }, [_c('p', {\n attrs: {\n \"id\": \"result_number\"\n }\n }, [_vm._v(_vm._s(_vm.tips))]), _vm._v(\" \"), _vm._l((_vm.part_response), function(item) {\n return _c('div', [_c('a', {\n staticClass: \"item_title\",\n attrs: {\n \"id\": \"title\",\n \"href\": item.url,\n \"target\": \"_blank\"\n }\n }, [_vm._v(_vm._s(item.title))]), _vm._v(\" \"), _c('p', {\n staticClass: \"item_description\"\n }, [_vm._v(_vm._s(item.description))]), _vm._v(\" \"), _c('li', {\n attrs: {\n \"id\": \"small_url_content\"\n }\n }, [_c('a', {\n attrs: {\n \"href\": item.url,\n \"id\": \"small_url\",\n \"target\": \"_blank\"\n }\n }, [_vm._v(_vm._s(item.url))])]), _vm._v(\" \"), _c('li', {\n attrs: {\n \"id\": \"date\"\n }\n }, [_vm._v(\" \" + _vm._s(item.date))])])\n })], 2), _vm._v(\" \"), _c('div', {\n attrs: {\n \"id\": \"footer\"\n }\n }, _vm._l((parseInt(_vm.length / 10) + 1), function(n) {\n return (_vm.show_button) ? _c('button', {\n on: {\n \"click\": function($event) {\n _vm.page_select = n\n }\n }\n }, [_vm._v(_vm._s(n))]) : _vm._e()\n }))])\n},staticRenderFns: []}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/vue-loader/lib/template-compiler?{\"id\":\"data-v-17d40f1c\"}!./~/vue-loader/lib/selector.js?type=template&index=0!./src/components/searchResult.vue\n// module id = 52\n// module chunks = 1","module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;\n return _c('div', {\n attrs: {\n \"id\": \"app\"\n }\n }, [_c('router-view', {\n attrs: {\n \"parent-query\": _vm.query\n },\n on: {\n \"childChange\": _vm.showResult\n }\n })], 1)\n},staticRenderFns: []}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/vue-loader/lib/template-compiler?{\"id\":\"data-v-3368385f\"}!./~/vue-loader/lib/selector.js?type=template&index=0!./src/App.vue\n// module id = 53\n// module chunks = 1","module.exports={render:function (){var _vm=this;var _h=_vm.$createElement;var _c=_vm._self._c||_h;\n return _c('div', {\n attrs: {\n \"id\": \"searchEngine\"\n }\n }, [_c('input', {\n directives: [{\n name: \"model\",\n rawName: \"v-model\",\n value: (_vm.query),\n expression: \"query\"\n }],\n attrs: {\n \"type\": \"text\",\n \"id\": \"text\"\n },\n domProps: {\n \"value\": (_vm.query)\n },\n on: {\n \"input\": [function($event) {\n if ($event.target.composing) { return; }\n _vm.query = $event.target.value\n }, _vm.change]\n }\n }), _vm._v(\" \"), _c('button', {\n attrs: {\n \"id\": \"button\"\n },\n on: {\n \"click\": _vm.submit\n }\n }, [_vm._v(\"search\")])])\n},staticRenderFns: []}\n\n\n//////////////////\n// WEBPACK FOOTER\n// ./~/vue-loader/lib/template-compiler?{\"id\":\"data-v-e082b27e\"}!./~/vue-loader/lib/selector.js?type=template&index=0!./src/components/searchEngine.vue\n// module id = 54\n// module chunks = 1"],"sourceRoot":""} -------------------------------------------------------------------------------- /dist/static/js/manifest.42e3257fe0dc6f03a838.js: -------------------------------------------------------------------------------- 1 | !function(e){function r(n){if(t[n])return t[n].exports;var o=t[n]={i:n,l:!1,exports:{}};return e[n].call(o.exports,o,o.exports,r),o.l=!0,o.exports}var n=window.webpackJsonp;window.webpackJsonp=function(t,c,a){for(var i,u,f,s=0,l=[];s 2 | 3 | 4 | 5 | search-engine 6 | 7 | 8 |
    9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /jsonToMySQL.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | # reload(sys) 4 | # sys.setdefaultencoding('utf8') 5 | 6 | import json 7 | import codecs 8 | import MySQLdb 9 | def read(): 10 | json_file = codecs.open("items.json", 'r', 'utf-8') 11 | data = json.load(json_file) 12 | return data 13 | 14 | def save(index_,url,description,date,title): 15 | try: 16 | db = MySQLdb.connect("localhost","root","666666","python",charset='utf8') 17 | 18 | data = (index_,url,description,date,title) 19 | 20 | cursor = db.cursor() 21 | except: 22 | 23 | print ("error") 24 | 25 | sql = "INSERT INTO `search_result` (`index_`, `url`, `description`, `date`, `title`) VALUES(%s,%s,%s,%s,%s)" 26 | 27 | 28 | try: 29 | cursor.execute(sql,data) 30 | 31 | db.commit() 32 | except: 33 | db.rollback() 34 | 35 | cursor.close() 36 | 37 | db.close() 38 | data = read() 39 | global index 40 | index = 400 41 | for line in data: 42 | #print line['description'][0] 43 | if(line['description'] and line['title']): 44 | save(index,line['url'],line['description'][0],'2017-04-15',line['title'][0]) 45 | index +=1 46 | #print index -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "search-engine", 3 | "version": "1.0.0", 4 | "description": "a tiny search engine based on vue.js and use scrapy,jieba,php to accomplish it", 5 | "author": "xujingguo ", 6 | "private": true, 7 | "scripts": { 8 | "dev": "node build/dev-server.js", 9 | "start": "node build/dev-server.js", 10 | "build": "node build/build.js", 11 | "unit": "cross-env BABEL_ENV=test karma start test/unit/karma.conf.js --single-run", 12 | "e2e": "node test/e2e/runner.js", 13 | "test": "npm run unit && npm run e2e" 14 | }, 15 | "dependencies": { 16 | "vue": "^2.2.2", 17 | "vue-router": "^2.3.0" 18 | }, 19 | "devDependencies": { 20 | "autoprefixer": "^6.7.2", 21 | "babel-core": "^6.22.1", 22 | "babel-loader": "^6.2.10", 23 | "babel-plugin-transform-runtime": "^6.22.0", 24 | "babel-preset-env": "^1.2.1", 25 | "babel-preset-stage-2": "^6.22.0", 26 | "babel-register": "^6.22.0", 27 | "chalk": "^1.1.3", 28 | "connect-history-api-fallback": "^1.3.0", 29 | "copy-webpack-plugin": "^4.0.1", 30 | "css-loader": "^0.26.1", 31 | "eventsource-polyfill": "^0.9.6", 32 | "express": "^4.14.1", 33 | "extract-text-webpack-plugin": "^2.0.0", 34 | "file-loader": "^0.10.0", 35 | "friendly-errors-webpack-plugin": "^1.1.3", 36 | "html-webpack-plugin": "^2.28.0", 37 | "http-proxy-middleware": "^0.17.3", 38 | "webpack-bundle-analyzer": "^2.2.1", 39 | "cross-env": "^3.1.4", 40 | "karma": "^1.4.1", 41 | "karma-coverage": "^1.1.1", 42 | "karma-mocha": "^1.3.0", 43 | "karma-phantomjs-launcher": "^1.0.2", 44 | "karma-phantomjs-shim": "^1.4.0", 45 | "karma-sinon-chai": "^1.2.4", 46 | "karma-sourcemap-loader": "^0.3.7", 47 | "karma-spec-reporter": "0.0.26", 48 | "karma-webpack": "^2.0.2", 49 | "lolex": "^1.5.2", 50 | "mocha": "^3.2.0", 51 | "chai": "^3.5.0", 52 | "sinon": "^2.1.0", 53 | "sinon-chai": "^2.8.0", 54 | "inject-loader": "^2.0.1", 55 | "babel-plugin-istanbul": "^3.1.2", 56 | "phantomjs-prebuilt": "^2.1.14", 57 | "chromedriver": "^2.27.2", 58 | "cross-spawn": "^5.0.1", 59 | "nightwatch": "^0.9.12", 60 | "selenium-server": "^3.0.1", 61 | "semver": "^5.3.0", 62 | "shelljs": "^0.7.6", 63 | "opn": "^4.0.2", 64 | "optimize-css-assets-webpack-plugin": "^1.3.0", 65 | "ora": "^1.1.0", 66 | "rimraf": "^2.6.0", 67 | "url-loader": "^0.5.8", 68 | "vue-loader": "^11.1.4", 69 | "vue-style-loader": "^2.0.0", 70 | "vue-template-compiler": "^2.2.4", 71 | "webpack": "^2.2.1", 72 | "webpack-dev-middleware": "^1.10.0", 73 | "webpack-hot-middleware": "^2.16.1", 74 | "webpack-merge": "^2.6.1" 75 | }, 76 | "engines": { 77 | "node": ">= 4.0.0", 78 | "npm": ">= 3.0.0" 79 | }, 80 | "browserslist": [ 81 | "> 1%", 82 | "last 2 versions", 83 | "not ie <= 8" 84 | ] 85 | } 86 | -------------------------------------------------------------------------------- /src/App.vue: -------------------------------------------------------------------------------- 1 | 6 | 7 | 25 | 26 | 30 | -------------------------------------------------------------------------------- /src/assets/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/xujingguo58/tinySearchEngine/8c8a7c5636b66c079ac835dbb5c6a20849b8447b/src/assets/logo.png -------------------------------------------------------------------------------- /src/components/searchEngine.vue: -------------------------------------------------------------------------------- 1 | 8 | 9 | 28 | 29 | 30 | 66 | -------------------------------------------------------------------------------- /src/components/searchResult.vue: -------------------------------------------------------------------------------- 1 | 21 | 22 | 105 | 106 | 107 | 215 | -------------------------------------------------------------------------------- /src/main.js: -------------------------------------------------------------------------------- 1 | // The Vue build version to load with the `import` command 2 | // (runtime-only or standalone) has been set in webpack.base.conf with an alias. 3 | import Vue from 'vue' 4 | import App from './App' 5 | import router from './router' 6 | import axios from 'axios' 7 | axios.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded'; 8 | Vue.prototype.$axios = axios 9 | 10 | Vue.config.productionTip = false 11 | 12 | /* eslint-disable no-new */ 13 | new Vue({ 14 | el: '#app', 15 | router, 16 | template: '', 17 | components: { App } 18 | }) 19 | -------------------------------------------------------------------------------- /src/router/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Router from 'vue-router' 3 | import searchEngine from '@/components/searchEngine' 4 | import searchResult from '@/components/searchResult' 5 | 6 | Vue.use(Router) 7 | 8 | export default new Router({ 9 | routes: [ 10 | { 11 | path: '/', 12 | name: 'searchEngine', 13 | component: searchEngine 14 | }, 15 | { 16 | path: '/result', 17 | name: 'searchResult', 18 | component: searchResult 19 | } 20 | ] 21 | }) 22 | -------------------------------------------------------------------------------- /test/e2e/custom-assertions/elementCount.js: -------------------------------------------------------------------------------- 1 | // A custom Nightwatch assertion. 2 | // the name of the method is the filename. 3 | // can be used in tests like this: 4 | // 5 | // browser.assert.elementCount(selector, count) 6 | // 7 | // for how to write custom assertions see 8 | // http://nightwatchjs.org/guide#writing-custom-assertions 9 | exports.assertion = function (selector, count) { 10 | this.message = 'Testing if element <' + selector + '> has count: ' + count 11 | this.expected = count 12 | this.pass = function (val) { 13 | return val === this.expected 14 | } 15 | this.value = function (res) { 16 | return res.value 17 | } 18 | this.command = function (cb) { 19 | var self = this 20 | return this.api.execute(function (selector) { 21 | return document.querySelectorAll(selector).length 22 | }, [selector], function (res) { 23 | cb.call(self, res) 24 | }) 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /test/e2e/nightwatch.conf.js: -------------------------------------------------------------------------------- 1 | require('babel-register') 2 | var config = require('../../config') 3 | 4 | // http://nightwatchjs.org/gettingstarted#settings-file 5 | module.exports = { 6 | src_folders: ['test/e2e/specs'], 7 | output_folder: 'test/e2e/reports', 8 | custom_assertions_path: ['test/e2e/custom-assertions'], 9 | 10 | selenium: { 11 | start_process: true, 12 | server_path: require('selenium-server').path, 13 | host: '127.0.0.1', 14 | port: 4444, 15 | cli_args: { 16 | 'webdriver.chrome.driver': require('chromedriver').path 17 | } 18 | }, 19 | 20 | test_settings: { 21 | default: { 22 | selenium_port: 4444, 23 | selenium_host: 'localhost', 24 | silent: true, 25 | globals: { 26 | devServerURL: 'http://localhost:' + (process.env.PORT || config.dev.port) 27 | } 28 | }, 29 | 30 | chrome: { 31 | desiredCapabilities: { 32 | browserName: 'chrome', 33 | javascriptEnabled: true, 34 | acceptSslCerts: true 35 | } 36 | }, 37 | 38 | firefox: { 39 | desiredCapabilities: { 40 | browserName: 'firefox', 41 | javascriptEnabled: true, 42 | acceptSslCerts: true 43 | } 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/e2e/runner.js: -------------------------------------------------------------------------------- 1 | // 1. start the dev server using production config 2 | process.env.NODE_ENV = 'testing' 3 | var server = require('../../build/dev-server.js') 4 | 5 | server.ready.then(() => { 6 | // 2. run the nightwatch test suite against it 7 | // to run in additional browsers: 8 | // 1. add an entry in test/e2e/nightwatch.conf.json under "test_settings" 9 | // 2. add it to the --env flag below 10 | // or override the environment flag, for example: `npm run e2e -- --env chrome,firefox` 11 | // For more information on Nightwatch's config file, see 12 | // http://nightwatchjs.org/guide#settings-file 13 | var opts = process.argv.slice(2) 14 | if (opts.indexOf('--config') === -1) { 15 | opts = opts.concat(['--config', 'test/e2e/nightwatch.conf.js']) 16 | } 17 | if (opts.indexOf('--env') === -1) { 18 | opts = opts.concat(['--env', 'chrome']) 19 | } 20 | 21 | var spawn = require('cross-spawn') 22 | var runner = spawn('./node_modules/.bin/nightwatch', opts, { stdio: 'inherit' }) 23 | 24 | runner.on('exit', function (code) { 25 | server.close() 26 | process.exit(code) 27 | }) 28 | 29 | runner.on('error', function (err) { 30 | server.close() 31 | throw err 32 | }) 33 | }) 34 | -------------------------------------------------------------------------------- /test/e2e/specs/test.js: -------------------------------------------------------------------------------- 1 | // For authoring Nightwatch tests, see 2 | // http://nightwatchjs.org/guide#usage 3 | 4 | module.exports = { 5 | 'default e2e tests': function (browser) { 6 | // automatically uses dev Server port from /config.index.js 7 | // default: http://localhost:8080 8 | // see nightwatch.conf.js 9 | const devServer = browser.globals.devServerURL 10 | 11 | browser 12 | .url(devServer) 13 | .waitForElementVisible('#app', 5000) 14 | .assert.elementPresent('.hello') 15 | .assert.containsText('h1', 'Welcome to Your Vue.js App') 16 | .assert.elementCount('img', 1) 17 | .end() 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /test/unit/index.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | 3 | Vue.config.productionTip = false 4 | 5 | // require all test files (files that ends with .spec.js) 6 | const testsContext = require.context('./specs', true, /\.spec$/) 7 | testsContext.keys().forEach(testsContext) 8 | 9 | // require all src files except main.js for coverage. 10 | // you can also change this to match only the subset of files that 11 | // you want coverage for. 12 | const srcContext = require.context('../../src', true, /^\.\/(?!main(\.js)?$)/) 13 | srcContext.keys().forEach(srcContext) 14 | -------------------------------------------------------------------------------- /test/unit/karma.conf.js: -------------------------------------------------------------------------------- 1 | // This is a karma config file. For more details see 2 | // http://karma-runner.github.io/0.13/config/configuration-file.html 3 | // we are also using it with karma-webpack 4 | // https://github.com/webpack/karma-webpack 5 | 6 | var webpackConfig = require('../../build/webpack.test.conf') 7 | 8 | module.exports = function (config) { 9 | config.set({ 10 | // to run in additional browsers: 11 | // 1. install corresponding karma launcher 12 | // http://karma-runner.github.io/0.13/config/browsers.html 13 | // 2. add it to the `browsers` array below. 14 | browsers: ['PhantomJS'], 15 | frameworks: ['mocha', 'sinon-chai', 'phantomjs-shim'], 16 | reporters: ['spec', 'coverage'], 17 | files: ['./index.js'], 18 | preprocessors: { 19 | './index.js': ['webpack', 'sourcemap'] 20 | }, 21 | webpack: webpackConfig, 22 | webpackMiddleware: { 23 | noInfo: true 24 | }, 25 | coverageReporter: { 26 | dir: './coverage', 27 | reporters: [ 28 | { type: 'lcov', subdir: '.' }, 29 | { type: 'text-summary' } 30 | ] 31 | } 32 | }) 33 | } 34 | -------------------------------------------------------------------------------- /test/unit/specs/Hello.spec.js: -------------------------------------------------------------------------------- 1 | import Vue from 'vue' 2 | import Hello from '@/components/Hello' 3 | 4 | describe('Hello.vue', () => { 5 | it('should render correct contents', () => { 6 | const Constructor = Vue.extend(Hello) 7 | const vm = new Constructor().$mount() 8 | expect(vm.$el.querySelector('.hello h1').textContent) 9 | .to.equal('Welcome to Your Vue.js App') 10 | }) 11 | }) 12 | -------------------------------------------------------------------------------- /urlToKeywords.py: -------------------------------------------------------------------------------- 1 | # -*- coding: utf-8 -*- 2 | import sys 3 | sys.path.append("../") 4 | import jieba 5 | import jieba.analyse 6 | import MySQLdb 7 | 8 | 9 | def save(index_,keywords,tf_idf): 10 | db = MySQLdb.connect("localhost","root","666666","python",charset='utf8') 11 | 12 | cursor = db.cursor() 13 | 14 | data = (index_,keywords,tf_idf) 15 | 16 | print tf_idf 17 | 18 | sql = "INSERT INTO `inverted index`(`index_`, `keywords`, `tf_idf`) VALUES(%s,%s,%s)" 19 | 20 | 21 | try: 22 | cursor.execute(sql,data) 23 | 24 | db.commit() 25 | except: 26 | print "error" 27 | db.rollback() 28 | 29 | cursor.close() 30 | 31 | db.close() 32 | 33 | def main(): 34 | db = MySQLdb.connect("localhost","root","666666","python",charset='utf8') 35 | 36 | cursor = db.cursor() 37 | 38 | sql_query = "SELECT * FROM `search_result` WHERE 1" 39 | 40 | 41 | try: 42 | cursor.execute(sql_query) 43 | 44 | searchResult = cursor.fetchall() 45 | 46 | for row in searchResult: 47 | print row[0] 48 | seg_list = jieba.analyse.extract_tags(row[2],topK=30,withWeight=True) 49 | for line in seg_list: 50 | save(row[0],line[0], line[1]) 51 | except: 52 | print "error" 53 | db.rollback() 54 | 55 | cursor.close() 56 | 57 | db.close() 58 | #seg_list = jieba.analyse.extract_tags(str2,topK=20,withWeight=True) 59 | #for line in seg_list: 60 | #save(line[0],line[1]) 61 | 62 | 63 | if __name__=="__main__": 64 | main() 65 | 66 | --------------------------------------------------------------------------------