精品欧美一区二区三区在线观看 _久久久久国色av免费观看性色_国产精品久久在线观看_亚洲第一综合网站_91精品又粗又猛又爽_小泽玛利亚一区二区免费_91亚洲精品国偷拍自产在线观看 _久久精品视频在线播放_美女精品久久久_欧美日韩国产成人在线

幾百行代碼完成百度搜索引擎,真的可以嗎?

系統
阿粉最近遇到一個需求,因為數據量沒有達到需要使用 ElasticSearch 的級別,也不想單獨部署一套集群,所以準備自己基于 Lucene 實現一個簡易的搜索服務。下面我們一起來看一下吧。

 [[347248]]

本文轉載自微信公眾號「Java極客技術」,作者鴨血粉絲 。轉載本文請聯系Java極客技術公眾號。  

Hello 大家好,我是鴨血粉絲,大家都叫我阿粉,搜索引擎想必大家一定不會默認,我們項目中經常使用的 ElasticSearch 就是一種搜索引擎,在我們的日志系統中必不可少,ELK 作為一個整體,基本上是運維標配了,另外目前的搜索引擎底層都是基于 Lucene 來實現的。

阿粉最近遇到一個需求,因為數據量沒有達到需要使用 ElasticSearch 的級別,也不想單獨部署一套集群,所以準備自己基于 Lucene 實現一個簡易的搜索服務。下面我們一起來看一下吧。

背景

**Lucene **是一套用于全文檢索和搜索的開放源碼程序庫,由 Apache 軟件基金會支持和提供。Lucene 提供了一個簡單卻強大的應用程序接口,能夠做全文索引和搜索。Lucene 是現在最受歡迎的免費 Java 信息檢索程序庫。

上面的解釋是來自維基百科,我們只需要知道 Lucene 可以進行全文索引和搜索就行了,這里的索引是動詞,意思是我們可以將文檔或者文章或者文件等數據進行索引記錄下來,索引過后,我們查詢起來就會很快。

索引這個詞有的時候是動詞,表示我們要索引數據,有的時候是名詞,我們需要根據上下文場景來判斷。新華字典前面的字母表或者書籍前面的目錄本質上都是索引。

接入

引入依賴

首先我們創建一個 SpringBoot 項目,然后在 pom 文件中加入如下內容,我這里使用的 lucene 版本是 7.2.1,

  1. <properties> 
  2.     <lucene.version>7.2.1</lucene.version> 
  3. </properties> 
  4.  
  5. <!-- Lucene核心庫 --> 
  6. <dependency> 
  7.  <groupId>org.apache.lucene</groupId> 
  8.  <artifactId>lucene-core</artifactId> 
  9.  <version>${lucene.version}</version> 
  10. </dependency> 
  11. <!-- Lucene解析庫 --> 
  12. <dependency> 
  13.  <groupId>org.apache.lucene</groupId> 
  14.  <artifactId>lucene-queryparser</artifactId> 
  15.  <version>${lucene.version}</version> 
  16. </dependency> 
  17. <!-- Lucene附加的分析庫 --> 
  18. <dependency> 
  19.  <groupId>org.apache.lucene</groupId> 
  20.  <artifactId>lucene-analyzers-common</artifactId> 
  21.  <version>${lucene.version}</version> 
  22. </dependency> 

索引數據

在使用 Lucene 之前我們需要先索引一些文件,然后再通過關鍵詞查詢出來,下面我們來模擬整個過程。為了方便我們這里模擬一些數據,正常的數據應該是從數據庫或者文件中加載的,我們的思路是這樣的:

  1. 生成多條實體數據;
  2. 將實體數據映射成 Lucene 的文檔形式;
  3. 索引文檔;
  4. 根據關鍵詞查詢文檔;

第一步我們先創建一個實體如下:

  1. import lombok.Data; 
  2.  
  3. @Data 
  4. public class ArticleModel { 
  5.     private String title; 
  6.     private String author; 
  7.     private String content; 

我們再寫一個工具類,用來索引數據,代碼如下:

  1. import org.apache.commons.collections.CollectionUtils; 
  2. import org.apache.commons.lang.StringUtils; 
  3. import org.apache.lucene.analysis.Analyzer; 
  4. import org.apache.lucene.analysis.standard.StandardAnalyzer; 
  5. import org.apache.lucene.document.*; 
  6. import org.apache.lucene.index.IndexWriter; 
  7. import org.apache.lucene.index.IndexWriterConfig; 
  8. import org.apache.lucene.store.Directory; 
  9. import org.apache.lucene.store.FSDirectory; 
  10. import org.springframework.beans.factory.annotation.Value; 
  11. import org.springframework.stereotype.Component; 
  12.  
  13. import java.io.IOException; 
  14. import java.nio.file.Paths; 
  15. import java.util.ArrayList; 
  16. import java.util.List; 
  17. import java.util.Map; 
  18.  
  19. public class LuceneIndexUtil { 
  20.  
  21.     private static String INDEX_PATH = "/opt/lucene/demo"
  22.     private static IndexWriter writer; 
  23.  
  24.     public static LuceneIndexUtil getInstance() { 
  25.         return SingletonHolder.luceneUtil; 
  26.     } 
  27.  
  28.     private static class SingletonHolder { 
  29.         public final static LuceneIndexUtil luceneUtil = new LuceneIndexUtil(); 
  30.     } 
  31.  
  32.     private LuceneIndexUtil() { 
  33.         this.initLuceneUtil(); 
  34.     } 
  35.  
  36.     private void initLuceneUtil() { 
  37.         try { 
  38.             Directory dir = FSDirectory.open(Paths.get(INDEX_PATH)); 
  39.             Analyzer analyzer = new StandardAnalyzer(); 
  40.             IndexWriterConfig iwc = new IndexWriterConfig(analyzer); 
  41.             writer = new IndexWriter(dir, iwc); 
  42.         } catch (IOException e) { 
  43.             log.error("create luceneUtil error"); 
  44.             if (null != writer) { 
  45.                 try { 
  46.                     writer.close(); 
  47.                 } catch (IOException ioException) { 
  48.                     ioException.printStackTrace(); 
  49.                 } finally { 
  50.                     writer = null
  51.                 } 
  52.             } 
  53.         } 
  54.     } 
  55.  
  56.     /** 
  57.      * 索引單個文檔 
  58.      * 
  59.      * @param doc 文檔信息 
  60.      * @throws IOException IO 異常 
  61.      */ 
  62.     public void addDoc(Document doc) throws IOException { 
  63.         if (null != doc) { 
  64.             writer.addDocument(doc); 
  65.             writer.commit(); 
  66.             writer.close(); 
  67.         } 
  68.     } 
  69.  
  70.     /** 
  71.      * 索引單個實體 
  72.      * 
  73.      * @param model 單個實體 
  74.      * @throws IOException IO 異常 
  75.      */ 
  76.     public void addModelDoc(Object model) throws IOException { 
  77.         Document document = new Document(); 
  78.         List<Field> fields = luceneField(model.getClass()); 
  79.         fields.forEach(document::add); 
  80.         writer.addDocument(document); 
  81.         writer.commit(); 
  82.         writer.close(); 
  83.     } 
  84.  
  85.     /** 
  86.      * 索引實體列表 
  87.      * 
  88.      * @param objects 實例列表 
  89.      * @throws IOException IO 異常 
  90.      */ 
  91.     public void addModelDocs(List<?> objects) throws IOException { 
  92.         if (CollectionUtils.isNotEmpty(objects)) { 
  93.             List<Document> docs = new ArrayList<>(); 
  94.             objects.forEach(o -> { 
  95.                 Document document = new Document(); 
  96.                 List<Field> fields = luceneField(o); 
  97.                 fields.forEach(document::add); 
  98.                 docs.add(document); 
  99.             }); 
  100.             writer.addDocuments(docs); 
  101.         } 
  102.     } 
  103.  
  104.     /** 
  105.      * 清除所有文檔 
  106.      * 
  107.      * @throws IOException IO 異常 
  108.      */ 
  109.     public void delAllDocs() throws IOException { 
  110.         writer.deleteAll(); 
  111.     } 
  112.  
  113.     /** 
  114.      * 索引文檔列表 
  115.      * 
  116.      * @param docs 文檔列表 
  117.      * @throws IOException IO 異常 
  118.      */ 
  119.     public void addDocs(List<Document> docs) throws IOException { 
  120.         if (CollectionUtils.isNotEmpty(docs)) { 
  121.             long startTime = System.currentTimeMillis(); 
  122.             writer.addDocuments(docs); 
  123.             writer.commit(); 
  124.             log.info("共索引{}個 Document,共耗時{} 毫秒", docs.size(), (System.currentTimeMillis() - startTime)); 
  125.         } else { 
  126.             log.warn("索引列表為空"); 
  127.         } 
  128.     } 
  129.  
  130.     /** 
  131.      * 根據實體 class 對象獲取字段類型,進行 lucene Field 字段映射 
  132.      * 
  133.      * @param modelObj 實體 modelObj 對象 
  134.      * @return 字段映射列表 
  135.      */ 
  136.     public List<Field> luceneField(Object modelObj) { 
  137.         Map<String, Object> classFields = ReflectionUtils.getClassFields(modelObj.getClass()); 
  138.         Map<String, Object> classFieldsValues = ReflectionUtils.getClassFieldsValues(modelObj); 
  139.  
  140.         List<Field> fields = new ArrayList<>(); 
  141.         for (String key : classFields.keySet()) { 
  142.             Field field; 
  143.             String dataType = StringUtils.substringAfterLast(classFields.get(key).toString(), "."); 
  144.             switch (dataType) { 
  145.                 case "Integer"
  146.                     field = new IntPoint(key, (Integer) classFieldsValues.get(key)); 
  147.                     break; 
  148.                 case "Long"
  149.                     field = new LongPoint(key, (Long) classFieldsValues.get(key)); 
  150.                     break; 
  151.                 case "Float"
  152.                     field = new FloatPoint(key, (Float) classFieldsValues.get(key)); 
  153.                     break; 
  154.                 case "Double"
  155.                     field = new DoublePoint(key, (Double) classFieldsValues.get(key)); 
  156.                     break; 
  157.                 case "String"
  158.                     String string = (String) classFieldsValues.get(key); 
  159.                     if (StringUtils.isNotBlank(string)) { 
  160.                         if (string.length() <= 1024) { 
  161.                             field = new StringField(key, (String) classFieldsValues.get(key), Field.Store.YES); 
  162.                         } else { 
  163.                             field = new TextField(key, (String) classFieldsValues.get(key), Field.Store.NO); 
  164.                         } 
  165.                     } else { 
  166.                         field = new StringField(key, StringUtils.EMPTY, Field.Store.NO); 
  167.                     } 
  168.                     break; 
  169.                 default
  170.                     field = new TextField(key, JsonUtils.obj2Json(classFieldsValues.get(key)), Field.Store.YES); 
  171.                     break; 
  172.             } 
  173.             fields.add(field); 
  174.         } 
  175.         return fields; 
  176.     } 
  177.     public void close() { 
  178.         if (null != writer) { 
  179.             try { 
  180.                 writer.close(); 
  181.             } catch (IOException e) { 
  182.                 log.error("close writer error"); 
  183.             } 
  184.             writer = null
  185.         } 
  186.     } 
  187.  
  188.     public void commit() throws IOException { 
  189.         if (null != writer) { 
  190.             writer.commit(); 
  191.             writer.close(); 
  192.         } 
  193.     } 

有了工具類,我們再寫一個 demo 來進行數據的索引

  1. import java.util.ArrayList; 
  2. import java.util.List; 
  3.  
  4. /** 
  5.  * <br> 
  6.  * <b>Function:</b><br> 
  7.  * <b>Author:</b>@author Silence<br> 
  8.  * <b>Date:</b>2020-10-17 21:08<br> 
  9.  * <b>Desc:</b>無<br> 
  10.  */ 
  11. public class Demo { 
  12.     public static void main(String[] args) { 
  13.         LuceneIndexUtil luceneUtil = LuceneIndexUtil.getInstance(); 
  14.         List<ArticleModel> articles = new ArrayList<>(); 
  15.         try { 
  16.             //索引數據 
  17.             ArticleModel article1 = new ArticleModel(); 
  18.             article1.setTitle("Java 極客技術"); 
  19.             article1.setAuthor("鴨血粉絲"); 
  20.             article1.setContent("這是一篇給大家介紹 Lucene 的技術文章,必定點贊評論轉發!!!"); 
  21.             ArticleModel article2 = new ArticleModel(); 
  22.             article2.setTitle("極客技術"); 
  23.             article2.setAuthor("鴨血粉絲"); 
  24.             article2.setContent("此處省略兩千字..."); 
  25.             ArticleModel article3 = new ArticleModel(); 
  26.             article3.setTitle("Java 極客技術"); 
  27.             article3.setAuthor("鴨血粉絲"); 
  28.             article3.setContent("最后邀請你加入我們的知識星球,Today is big day!"); 
  29.             articles.add(article1); 
  30.             articles.add(article2); 
  31.             articles.add(article3); 
  32.             luceneUtil.addModelDocs(articles); 
  33.             luceneUtil.commit(); 
  34.              
  35.         } catch (Exception e) { 
  36.             e.printStackTrace(); 
  37.         } 
  38.     } 

上面的 content 內容可以自行進行替換,阿粉這邊避免湊字數的嫌疑就不貼了。

展示

運行結束過后,我們用過 Lucene 的可視化工具 luke 來查看下索引的數據內容,下載過后解壓我們可以看到有.bat 和 .sh 兩個腳本,根據自己的系統進行運行就好了。阿粉這邊是 mac 用的是 sh 腳本運行,運行后打開設置的索引目錄即可。

進入過后,我們可以看到下圖顯示的內容,選擇 content 點擊 show top items 可以看到右側的索引數據,這里根據分詞器的不同,索引的結果是不一樣的,阿粉這里采用的分詞器就是標準的分詞器,小伙伴們可以根據自己的要求選擇適合自己的分詞器即可。

搜索數據

數據已經索引成功了,接下來我們就需要根據條件進行數據的搜索了,我們創建一個 LuceneSearchUtil.java 來操作數據。

  1. import org.apache.commons.collections.MapUtils; 
  2. import org.apache.lucene.analysis.Analyzer; 
  3. import org.apache.lucene.analysis.standard.StandardAnalyzer; 
  4. import org.apache.lucene.index.DirectoryReader; 
  5. import org.apache.lucene.queryparser.classic.QueryParser; 
  6. import org.apache.lucene.search.*; 
  7. import org.apache.lucene.store.Directory; 
  8. import org.apache.lucene.store.FSDirectory; 
  9. import org.springframework.beans.factory.annotation.Value; 
  10.  
  11. import java.io.IOException; 
  12. import java.nio.file.Paths; 
  13. import java.util.Map; 
  14.  
  15.  
  16. public class LuceneSearchUtil { 
  17.  
  18.     private static String INDEX_PATH = "/opt/lucene/demo"
  19.     private static IndexSearcher searcher; 
  20.  
  21.     public static LuceneSearchUtil getInstance() { 
  22.         return LuceneSearchUtil.SingletonHolder.searchUtil; 
  23.     } 
  24.  
  25.     private static class SingletonHolder { 
  26.         public final static LuceneSearchUtil searchUtil = new LuceneSearchUtil(); 
  27.     } 
  28.  
  29.     private LuceneSearchUtil() { 
  30.         this.initSearcher(); 
  31.     } 
  32.  
  33.     private void initSearcher() { 
  34.         Directory directory; 
  35.         try { 
  36.             directory = FSDirectory.open(Paths.get(INDEX_PATH)); 
  37.             DirectoryReader reader = DirectoryReader.open(directory); 
  38.             searcher = new IndexSearcher(reader); 
  39.         } catch (IOException e) { 
  40.             e.printStackTrace(); 
  41.         } 
  42.     } 
  43.  
  44.     public TopDocs searchByMap(Map<String, Object> queryMap) throws Exception { 
  45.         if (null == searcher) { 
  46.             this.initSearcher(); 
  47.         } 
  48.         if (MapUtils.isNotEmpty(queryMap)) { 
  49.             BooleanQuery.Builder builder = new BooleanQuery.Builder(); 
  50.             queryMap.forEach((key, value) -> { 
  51.                 if (value instanceof String) { 
  52.                     Query queryString = new PhraseQuery(key, (String) value); 
  53. //                    Query queryString = new TermQuery(new Term(key, (String) value)); 
  54.                     builder.add(queryString, BooleanClause.Occur.MUST); 
  55.                 } 
  56.             }); 
  57.             return searcher.search(builder.build(), 10); 
  58.         } 
  59.         return null
  60.     } 
  61.  

在 demo.java 中增加搜索代碼如下:

  1. //查詢數據 
  2.    Map<String, Object> map = new HashMap<>(); 
  3.    map.put("title""Java 極客技術"); 
  4. //   map.put("title""極客技術"); 
  5. //   map.put("content""最"); 
  6.    LuceneSearchUtil searchUtil = LuceneSearchUtil.getInstance(); 
  7.    TopDocs topDocs = searchUtil.searchByMap(map); 
  8.    System.out.println(topDocs.totalHits); 

運行結果如下,表示搜索到了兩條。

通過可視化工具我們可以看到 title 為"Java 極客技術"確實是有兩條記錄,而且我們也確認只插入了兩條數據。注意這里如果根據其他字符去查詢可能查詢不出來,因為阿粉這里的分詞器采用的是默認的分詞器,小伙伴可以根據自身的情況采用相應的分詞器。

至此我們可以索引和搜索數據了,不過這還是簡單的入門操作,對于不同類型的字段,我們需要使用不同的查詢方式,而且根據系統的特性我們需要使用特定的分詞器,默認的標準分詞器不一定符合我們的使用場景。而且我們索引數據的時候也需要根據字段類型進行不同 Field 的設定。上面的案例只是 demo 并不能在生產上使用,搜索引擎在互聯網行業是領頭羊,很多先進的互聯網技術都是從搜索引擎開始發展的。

 

責任編輯:武曉燕 來源: Java極客技術
相關推薦

2010-05-06 13:32:59

2011-05-17 18:01:52

搜索引擎優化

2011-11-15 08:40:17

百度

2011-10-28 16:19:21

百度搜索

2009-08-07 08:29:36

百度搜索引擎

2022-11-18 12:06:48

App接口搜索

2023-01-11 12:49:49

AIChatGPT

2020-06-04 13:41:35

大數據疫情技術

2021-01-28 06:07:32

百度搜索搜索引擎 應用

2018-10-19 10:05:14

區塊鏈百度百度搜索

2012-11-25 15:42:47

互聯網百度搜索

2009-12-04 09:27:02

搜索引擎色情

2018-06-13 17:43:46

熊掌號

2012-04-06 09:23:09

百度蘋果

2020-03-17 08:23:47

搜索引擎百度Google

2012-11-16 11:01:50

移動搜索ASO

2011-06-29 16:02:40

jQuery

2010-08-12 22:20:14

百度搜索營銷培訓
點贊
收藏

51CTO技術棧公眾號

婷婷久久青草热一区二区 | 久久亚洲电影| 中日韩美女免费视频网址在线观看 | 亚洲性xxxx| 免费黄视频在线观看| 狠狠操一区二区三区| 国产日韩三级在线| 亚洲a区在线视频| 91视频免费网址| 999国产精品永久免费视频app| 日韩一区二区三区四区| av无码久久久久久不卡网站| 毛片网站在线观看| 国产成人亚洲综合a∨猫咪| 欧美专区在线观看| 欧美三级在线免费观看| 国产区精品区| 亚洲高清久久网| 在线播放av中文字幕| 18video性欧美19sex高清| 亚洲国产精品精华液2区45| 国产精品一区二区不卡视频| 中文字幕一区二区三区四区免费看| 国模 一区 二区 三区| 正在播放欧美一区| 免费成人深夜夜行p站| 久久久久毛片免费观看| 在线免费观看日韩欧美| 欧美爱爱视频免费看| 国产高清一区二区三区视频| 久久综合久久99| 成人欧美视频在线| 国产精品自拍电影| 日韩国产精品91| 国产91对白在线播放| 激情小说中文字幕| 久久精品国产www456c0m| 亚洲欧美激情在线视频| 日本黄色录像片| 日本在线一区二区三区| 欧美日韩亚洲高清一区二区| 成年人网站大全| 成人影院大全| 91成人在线精品| 日韩在线综合网| 俺来也官网欧美久久精品| 亚洲免费看黄网站| 午夜在线视频免费观看| 成人三级黄色免费网站| 久久精品人人做| 欧美一区国产一区| 蜜芽tv福利在线视频| 91蜜桃在线免费视频| 精品免费一区二区三区蜜桃| 香蕉久久国产av一区二区| 99久久国产免费看| 久久av一区二区三区漫画| 日韩在线视频免费| 99riav一区二区三区| 久久久久久国产精品免费免费| 天天操天天插天天射| 99精品热视频| 欧洲国产精品| 9色在线视频网站| 国产精品电影一区二区三区| 最近看过的日韩成人| 国产在线69| 一区二区三区四区高清精品免费观看| 国产精品igao激情视频| wwww亚洲| 日本高清免费不卡视频| 亚洲国产精品三区| 成人综合日日夜夜| 精品粉嫩aⅴ一区二区三区四区| www国产视频| 国产乱码精品一区二区三区四区 | 人人干在线视频| 日韩久久一区二区| xxxx18hd亚洲hd捆绑| 神马久久午夜| 欧美日韩一区二区三区四区| av在线网址导航| 99精品国产一区二区三区2021| 亚洲国产日韩欧美在线动漫| 亚洲日本精品视频| 五月激情久久久| 五月天亚洲婷婷| 久久久久狠狠高潮亚洲精品| 91精品国产66| 日韩欧美美女一区二区三区| 国产精品无码在线| 久久国产中文字幕| 久久久免费av| 一区二区乱子伦在线播放| 国产一区二区三区在线观看免费视频| 国产v亚洲v天堂无码| 可以在线观看的av| 一区二区三区不卡视频在线观看 | 蜜桃一区二区三区在线| 动漫一区二区在线| 第一页在线观看| 亚洲午夜成aⅴ人片| 日本va中文字幕| av资源新版天堂在线| 色综合天天性综合| 久久发布国产伦子伦精品| 久久成人高清| 久久久久国色av免费观看性色| 成年人视频免费| 亚洲欧美激情诱惑| 亚洲一区二区三区在线视频 | 精品国产一区二区三区久久久狼| 日韩免费一二三区| 精品综合免费视频观看| 久久久久网址| 丁香花在线高清完整版视频| 欧美日产在线观看| 欧洲av一区二区三区| 精久久久久久| av成人观看| 麻豆网站在线| 欧美视频三区在线播放| 最近中文字幕无免费| 亚洲mv大片欧洲mv大片| 日韩av免费在线看| 无码国产精品一区二区色情男同| 亚洲欧美日韩国产成人精品影院| 九九热免费精品视频| 外国成人在线视频| 性欧美xxxx交| 韩国中文字幕hd久久精品| 日韩理论片中文av| 黄色aaaaaa| 五月天综合网站| 国产欧美精品在线播放| jzzjzzjzz亚洲成熟少妇| 高跟丝袜一区二区三区| 北京富婆泄欲对白| 影音先锋亚洲电影| 精品国产乱码一区二区三区四区| 国产亚av手机在线观看| 精品日韩一区二区| 国产性猛交普通话对白| 懂色av一区二区三区免费观看| 国产奶头好大揉着好爽视频| av在线亚洲一区| 日韩专区在线播放| 一级全黄裸体免费视频| 国产精品福利一区二区| 色婷婷一区二区三区在线观看| 91精品一区二区三区综合在线爱| 91久久精品日日躁夜夜躁国产| 伊人免费在线| 91精品国产乱| 免费一级片在线观看| 懂色av噜噜一区二区三区av| 国产素人在线观看| 妖精视频一区二区三区| 欧美一级淫片丝袜脚交| 熟妇人妻系列aⅴ无码专区友真希 熟妇人妻av无码一区二区三区 | 成人黄视频在线观看| 欧美一区中文字幕| 麻豆国产尤物av尤物在线观看| 国产不卡在线一区| 尤物av无码色av无码| 国产欧美日韩精品一区二区三区 | 久久久不卡网国产精品二区 | 日韩电影免费观| 在线播放日韩专区| 国产特黄一级片| 亚洲国产精品影院| 精品国产av无码| 麻豆精品一区二区av白丝在线| 亚洲小视频在线播放| 风间由美中文字幕在线看视频国产欧美 | 国内老司机av在线| 亚洲精品一区中文字幕乱码| 自拍偷拍色综合| 亚洲妇熟xx妇色黄| 熟女俱乐部一区二区| 久久se精品一区二区| 大荫蒂性生交片| gogo亚洲高清大胆美女人体| 国产一区二区av| 国产激情久久久久久熟女老人av| 亚洲第一福利一区| 我不卡一区二区| 国产电影一区二区三区| 女人另类性混交zo| 亚洲情侣在线| 欧美精品在线一区| 久久九九精品视频| 国产精品99久久久久久www| 99在线播放| 亚洲深夜福利在线| 午夜精品久久久久久久第一页按摩 | 久久久国产一区| 三级理论午夜在线观看| 欧美一卡二卡在线| 色老头一区二区| 一区二区三区成人在线视频| 午夜影院黄色片| 99re6这里只有精品视频在线观看| 日本肉体xxxx裸体xxx免费| 亚洲日本视频| 大桥未久一区二区三区| 久久不见久久见免费视频7| 国产91免费视频| 欧美三级电影网址| 欧洲成人在线观看| 久久国产精品黑丝| 久久伊人91精品综合网站| 日韩欧美亚洲系列| 欧美精品一区视频| 国产精品无码在线播放| 91精品1区2区| 日产精品久久久| 亚洲国产精品久久艾草纯爱| 亚洲波多野结衣| 国产精品午夜春色av| 久久国产精品无码一级毛片| 国产一区二区三区免费观看| 欧美特级aaa| 日精品一区二区| aa免费在线观看| 亚洲精品男同| 欧美精品久久久久久久久久久| 亚洲成人一区| 一区精品在线| 99精品视频在线| 亚洲开发第一视频在线播放| 国产不卡一区| 日韩av不卡播放| 狠狠操综合网| 欧美二区在线| 日韩在线影视| 久久亚洲综合网| 色婷婷久久久| 久久久久天天天天| 亚洲人亚洲人色久| 欧美日本韩国国产| 欧美日韩黑人| 午夜一区二区三区| 久久中文字幕二区| 一区精品视频| 欧美日韩国产色综合一二三四| 99视频精品全部免费看| 中文一区一区三区免费在线观看| 亚洲欧美一二三| 欧美freesex交免费视频| 美女在线免费视频| 欧美日韩国产高清| av高清在线免费观看| 国产欧美一区二区色老头| 国产极品尤物在线| 蜜桃伊人久久| 亚欧在线免费观看| 麻豆精品视频在线观看免费 | av亚洲精华国产精华精华| 在线精品视频播放| 91在线精品一区二区三区| 欧美精品黑人猛交高潮| 中文字幕二三区不卡| 久久人妻无码aⅴ毛片a片app| 亚洲女与黑人做爰| 国产午夜视频在线播放| 一本一本久久a久久精品综合麻豆| 欧美人一级淫片a免费播放| 欧美日韩国产系列| www香蕉视频| 精品调教chinesegay| av在线免费观看网| 美日韩精品免费视频| 高端美女服务在线视频播放| 日本国产高清不卡| 白嫩亚洲一区二区三区| 国产免费一区二区| 国产亚洲一区二区三区不卡| 精品国产无码在线| 日韩天天综合| 中国黄色片一级| 波多野结衣视频一区| 人人人妻人人澡人人爽欧美一区| 亚洲女厕所小便bbb| 日本中文字幕在线免费观看| 欧美午夜在线观看| 午夜精品久久久久久久第一页按摩 | 欧美天堂在线观看| 一本大道伊人av久久综合| 精品国产免费久久| a黄色在线观看| 欧美精品18videosex性欧美| 日本免费久久| 国产精品入口免费| 日韩国产欧美| 日韩五码在线观看| 久久99国内精品| 亚洲人人夜夜澡人人爽| 综合久久给合久久狠狠狠97色 | 青草在线视频| 国产美女直播视频一区| 色天天色综合| 性高湖久久久久久久久aaaaa| 美女网站视频久久| av黄色免费网站| 午夜久久久久久| 国产精品一区二区av白丝下载 | 中字幕一区二区三区乱码 | 中文字幕精品在线观看| 亚洲精品理论电影| h片在线观看网站| 国产精品入口夜色视频大尺度| 你懂的在线观看一区二区| 2025韩国大尺度电影| 秋霞午夜av一区二区三区| 99re这里只有| 一区二区日韩av| 97人妻精品一区二区三区软件| 亚洲视频自拍偷拍| 三级中文字幕在线观看| 99久久99久久精品国产片| 999久久久91| 日本人69视频| 国产精品久久久爽爽爽麻豆色哟哟| 国产性猛交╳xxx乱大交| 精品国产一区二区三区av性色 | 欧美在线亚洲在线| 加勒比视频一区| 97超碰国产精品| 国产精品一区在线观看乱码 | 成人在线免费看| 日韩av观看网址| 神马影视一区二区| 男人操女人免费| 久久天天做天天爱综合色| 久久狠狠高潮亚洲精品| 精品国产百合女同互慰| av在线免费网站| 97久久夜色精品国产九色 | 欧美日韩一区二区三区不卡视频| 日本一级黄视频| 国产成人精品网址| 九九免费精品视频| 欧美成人精品二区三区99精品| av毛片在线免费看| 91|九色|视频| 亚洲夜间福利| 麻豆国产精品一区| 色婷婷久久久亚洲一区二区三区| 理论视频在线| 国产精品一区二区三区久久久| 久久国产亚洲| 特种兵之深入敌后| 亚洲国产综合人成综合网站| 深爱五月激情五月| 日本精品视频在线播放| 精品高清在线| 午夜国产福利在线观看| 亚洲欧洲制服丝袜| 后进极品白嫩翘臀在线视频| 国模精品视频一区二区| 精品在线播放| 日本黄色的视频| 亚洲一区二区美女| 日韩精品福利| 国产欧美在线看| 国产精品av久久久久久麻豆网| xxxxxx黄色| 欧美在线免费观看亚洲| 中文字幕中文字幕在线中高清免费版| 超碰97在线人人| 麻豆9191精品国产| 久久久久人妻一区精品色| 日韩免费一区二区| 欧美粗大gay| 潘金莲一级淫片aaaaaa播放1| 99热这里都是精品| 丰满熟女人妻一区二区三| 久久av中文字幕| 天美av一区二区三区久久| 视频二区在线播放| 亚洲自拍偷拍麻豆| 黄色av网站在线看| 亚洲综合小说区| 久久黄色影院| 清纯粉嫩极品夜夜嗨av| 亚洲香蕉成视频在线观看| 亚洲精品一二三**| 免费激情视频在线观看| 亚洲精品免费视频| 黄色片在线播放| 99影视tv| 日韩精品成人一区二区在线| 欧美成人国产精品高潮| 亚洲午夜未满十八勿入免费观看全集 | 国产综合精品一区| а天堂中文在线资源| 亚洲精品720p| 欧美三级一区| 成年人在线观看视频免费|