3atv精品不卡视频,97人人超碰国产精品最新,中文字幕av一区二区三区人妻少妇,久久久精品波多野结衣,日韩一区二区三区精品

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

爬虫教程( 6 ) --- 爬虫 进阶、扩展

發布時間:2023/12/14 编程问答 31 豆豆
生活随笔 收集整理的這篇文章主要介紹了 爬虫教程( 6 ) --- 爬虫 进阶、扩展 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

1. 前言

1. 先看一個最簡單的爬蟲。

import requestsurl = "http://www.cricode.com" r = requests.get(url) print(r.text)

2. 一個正常的爬蟲程序

上面那個最簡單的爬蟲,是一個不完整的殘疾的爬蟲。因為爬蟲程序通常需要做的事情如下:

  • 1)給定的種子 URLs,爬蟲程序將所有種子 URL 頁面爬取下來
  • 2)爬蟲程序解析爬取到的 URL 頁面中的鏈接,將這些鏈接放入待爬取 URL 集合中
  • 3)重復 1、2 步,直到達到指定條件才結束爬取

因此,一個完整的爬蟲大概是這樣子的:

import requests # 用來爬取網頁 from bs4 import BeautifulSoup # 用來解析網頁# 我們的種子 seeds = ["http://www.hao123.com","http://www.csdn.net","http://www.cricode.com" ]# 設定終止條件為:爬取到 100000個頁面時就停止爬取 end_sum = 0def do_save_action(text=None):passwhile end_sum < 10000:if end_sum < len(seeds):r = requests.get(seeds[end_sum])end_sum = end_sum + 1do_save_action(r.text)soup = BeautifulSoup(r.content)urls = soup.find_all('a') # 解析網頁for url in urls:seeds.append(url)else:break

3. 現在來找茬。上面那個完整的爬蟲,缺點實在是太多。下面一一列舉它的N宗罪:

  • 1)我們的任務是爬取1萬個網頁,按上面這個程序,一個人在默默的爬取,假設爬起一個網頁3秒鐘,那么,爬一萬個網頁需要3萬秒鐘。MGD,我們應當考慮開啟多個線程(池)去一起爬取,或者用分布式架構去并發的爬取網頁。
  • 2)種子URL后續解析到的URL 都放在一個列表里,應該設計一個更合理的數據結構來存放這些待爬取的 URL ,比如:隊列或者優先隊列。( scrapy-redis 是 種子URL redis的 list 里面后續解析到的URL 隊列里面?)
  • 3)對各個網站的 url,我們一視同仁,事實上,我們應當區別對待。大站好站優先原則應當予以考慮。
  • 4)每次發起請求,都是根據 url 發起請求,而這個過程中會牽涉到 DNS 解析,將 url 轉換成 ip 地址。一個網站通常由成千上萬的 URL,因此,可以考慮將這些網站域名的 IP 地址進行緩存,避免每次都發起 DNS 請求,費時費力。
  • 5)解析到網頁中的 urls 后,我們沒有做任何去重處理,全部放入待爬取的列表中。事實上,可能有很多鏈接是重復的,我們做了很多重復勞動。
  • 6)…..

4.找了這么多茬后,現在討論一下問題的解決方案。

  • 1)并行爬取問題。我們可以有多種方法去實現并行。多線程或者線程池方式,一個爬蟲程序內部開啟多個線程。同一臺機器開啟多個爬蟲程序,如此,我們就有N多爬取線程在同時工作。能大大減少時間。此外,當我們要爬取的任務特別多時,一臺機器、一個網點肯定是不夠的,我們必須考慮分布式爬蟲。常見的分布式架構有:主從(Master——Slave)架構、點對點(Peer to Peer)架構,混合架構等。說到分布式架構,那我們需要考慮的問題就有很多,我們需要分派任務,各個爬蟲之間需要通信合作,共同完成任務,不要重復爬取相同的網頁。分派任務我們要做到公平公正,就需要考慮如何進行負載均衡。負載均衡,我們第一個想到的就是Hash,比如根據網站域名進行hash。負載均衡分派完任務之后,千萬不要以為萬事大吉了,萬一哪臺機器掛了呢?原先指派給掛掉的哪臺機器的任務指派給誰?又或者哪天要增加幾臺機器,任務有該如何進行重新分配呢 ?一個比較好的解決方案是用一致性 Hash 算法。
  • 2)待爬取網頁隊列。如何對待待抓取隊列,跟操作系統如何調度進程是類似的場景。不同網站,重要程度不同,因此,可以設計一個優先級隊列來存放待爬起的網頁鏈接。如此一來,每次抓取時,我們都優先爬取重要的網頁。當然,你也可以效仿操作系統的進程調度策略之多級反饋隊列調度算法。
  • 3)DNS緩存。為了避免每次都發起DNS查詢,我們可以將DNS進行緩存。DNS緩存當然是設計一個hash表來存儲已有的域名及其IP。
  • 4)網頁去重。說到網頁去重,第一個想到的是垃圾郵件過濾。垃圾郵件過濾一個經典的解決方案是 Bloom Filter(布隆過濾器)。布隆過濾器原理簡單來說就是:建立一個大的位數組,然后用多個 Hash 函數對同一個 url 進行 hash 得到多個數字,然后將位數組中這些數字對應的位置為1。下次再來一個url時,同樣是用多個Hash函數進行hash,得到多個數字,我們只需要判斷位數組中這些數字對應的為是全為1,如果全為1,那么說明這個url已經出現過。如此,便完成了url去重的問題。當然,這種方法會有誤差,只要誤差在我們的容忍范圍之類,比如1萬個網頁,我只爬取到了9999個,也是可以忍受滴。。。
  • 5)數據存儲的問題。數據存儲同樣是個很有技術含量的問題。用關系數據庫存取還是用 NoSQL,或是自己設計特定的文件格式進行存儲,都大有文章可做。
  • 6)進程間通信。分布式爬蟲,就必然離不開進程間的通信。我們可以以規定的數據格式進行數據交互,完成進程間通信。
  • 7)……

如何實現上面這些東西 ???

實現的過程中,你會發現,我們要考慮的問題遠遠不止上面這些。紙上得來終覺淺,覺知此事要躬行!

2. 如何 "跟蹤"?和 "過濾"

在很多情況下,我們并不是只抓取某個頁面,而需要 "順藤摸瓜",從幾個種子頁面,通過超級鏈接索,最終定位到我們想要的頁面。Scrapy 對這個功能進行了很好的抽象:

from abc import ABCfrom scrapy.spiders import CrawlSpider, Rule from scrapy.linkextractors import LinkExtractor from scrapy.selector import Selector from scrapy.item import Itemclass Coder4Spider(CrawlSpider, ABC):name = 'coder4'allowed_domains = ['xxx.com']start_urls = ['http://www.xxx.com']rules = (Rule(LinkExtractor(allow=('page/[0-9]+',))),Rule(LinkExtractor(allow=('archives/[0-9]+',)), callback='parse_item'),)def parse_item(self, response):self.log(f'request url : {response.url}')

在上面,我們用了 CrawlSpider 而不是 Spider。其中 name、 allowed_domains、start_urls 就不解釋了。

重點說下 Rule:

  • 第 1 條不帶 callback 的,表示只是 “跳板”,即只下載網頁并根據 allow 中匹配的鏈接,去繼續遍歷下一步的頁面,實際上 Rule 還可以指定 deny=xxx 表示過濾掉哪些頁面。

  • 第 2 條帶 callback 的,是最終會回調 parse_item 函數的網頁。

3. 如何 "過濾重復" 的頁面

Scrapy 支持通過 RFPDupeFilter 來完成頁面的去重(防止重復抓取)。

DUPEFILTER_CLASS = 'scrapy.dupefilters.RFPDupeFilter'

RFPDupeFilter 實際是根據 request_fingerprint 實現過濾的。

源碼中實現如下:

def request_fingerprint(request, include_headers=None, keep_fragments=False):if include_headers:include_headers = tuple(to_bytes(h.lower()) for h in sorted(include_headers))cache = _fingerprint_cache.setdefault(request, {})cache_key = (include_headers, keep_fragments)if cache_key not in cache:fp = hashlib.sha1()fp.update(to_bytes(request.method))fp.update(to_bytes(canonicalize_url(request.url, keep_fragments=keep_fragments)))fp.update(request.body or b'')if include_headers:for hdr in include_headers:if hdr in request.headers:fp.update(hdr)for v in request.headers.getlist(hdr):fp.update(v)cache[cache_key] = fp.hexdigest()return cache[cache_key]

我們可以看到,去重指紋是 sha1(method + url + body + header),所以,實際能夠去掉重復的比例并不大。如果我們需要自己提取去重的 finger,需要自己實現 Filter,并配置上它。下面這個 Filter 只根據 url 去重:

from scrapy.dupefilters import RFPDupeFilterclass SeenURLFilter(RFPDupeFilter):"""A dupe filter that considers the URL"""def __init__(self, path=None):self.urls_seen = set()RFPDupeFilter.__init__(self, path)def request_seen(self, request):if request.url in self.urls_seen:return Trueelse:self.urls_seen.add(request.url)

不要忘記配置上:

DUPEFILTER_CLASS ='scraper.custom_filters.SeenURLFilter'

4. 海量數據處理算法 Bloom Filter

海量數據處理算法—Bloom Filter:https://www.cnblogs.com/zhxshseu/p/5289871.html

結合 Guava 源碼解讀布隆過濾器:http://cyhone.com/2017/02/07/Introduce-to-BloomFilter/

更多:https://www.baidu.com/s?wd=Bloomfilter%20%E7%AE%97%E6%B3%95

Bloom-Filter,即布隆過濾器,1970年由 Bloom 中提出。是一種多哈希函數映射的快速查找算法。通常應用在一些需要快速判斷某個元素是否屬于集合,但是并不嚴格要求100%正確的場合。Bloom Filter 有可能會出現錯誤判斷,但不會漏掉判斷。也就是Bloom Filter 如果判斷元素不在集合中,那肯定就是不在。如果判斷元素存在集合中,有一定的概率判斷錯誤。。。

因此,Bloom Filter 不適合那些 "零錯誤"?的應用場合。而在能容忍低錯誤率的應用場合下,Bloom Filter 比其他常見的算法(如hash,折半查找)極大節省了空間。

  • 優點是空間效率和查詢時間都遠遠超過一般的算法,
  • 缺點是有一定的誤識別率和刪除困難。

一. 實例

為了說明 Bloom Filter 存在的重要意義,舉一個實例:假設要你寫一個網絡蜘蛛(web crawler)。由于網絡間的鏈接錯綜復雜,蜘蛛在網絡間爬行很可能會形成 “環”。為了避免形成“環”,就需要知道蜘蛛已經訪問過那些 URL。給一個 URL,怎樣知道蜘蛛是否已經訪問過呢?稍微想想,就會有如下幾種方案:

  • 1. 將訪問過的 URL 保存到數據庫。
  • 2. 用 HashSet 將訪問過的 URL 保存起來。那只需接近 O(1) 的代價就可以查到一個 URL 是否被訪問過了。
  • 3. URL 經過 MD5 或 SHA-1 等單向哈希后再保存到 HashSet 或數據庫。
  • 4. Bit-Map 方法。建立一個 BitSet,將每個 URL 經過一個哈希函數映射到某一位。

方法 1~3 都是將訪問過的 URL 完整保存,方法4 則只標記 URL 的一個映射位。以上方法在數據量較小的情況下都能完美解決問題,但是當數據量變得非常龐大時問題就來了。

  • 方法 1 的 缺點:數據量變得非常龐大后關系型數據庫查詢的效率會變得很低。而且每來一個URL就啟動一次數據庫查詢是不是太小題大做了?
  • 方法 2 的 缺點:太消耗內存。隨著 URL 的增多,占用的內存會越來越多。就算只有1億個 URL,每個 URL 只算 50 個字符,就需要 5GB 內存。
  • 方法 3 :由于字符串經過 MD5 處理后的信息摘要長度只有128Bit,SHA-1 處理后也只有 160Bit,因此 方法3 比 方法2 節省了好幾倍的內存。
  • 方法 4 :消耗內存是相對較少的,但缺點是單一哈希函數發生沖突的概率太高。還記得數據結構課上學過的 Hash 表沖突的各種解決方法么?若要降低沖突發生的概率到1%,就要將 BitSet 的長度設置為 URL 個數的 100 倍。

實質上,上面的算法都忽略了一個重要的隱含條件:允許小概率的出錯,不一定要100%準確!也就是說少量 url 實際上沒有沒網絡蜘蛛訪問,而將它們錯判為已訪問的代價是很小的——大不了少抓幾個網頁唄。

二. Bloom Filter 的算法

? ? ? ? 廢話說到這里,下面引入本篇的主角——Bloom Filter。其實上面方法4的思想已經很接近 Bloom Filter 了。方法四的致命缺點是沖突概率高,為了降低沖突的概念,Bloom Filter 使用了多個哈希函數,而不是一個。

? ? ? ? Bloom Filter 算法如下:創建一個 m位 BitSet,先將所有位初始化為0,然后選擇 k個 不同的哈希函數。第 i個 哈希函數對 字符串str 哈希的結果記為 h(i,str),且 h(i,str)的范圍是 0 到 m-1 。

  • (1) 加入字符串過程。下面是每個字符串處理的過程,首先是將字符串 str “記錄” 到 BitSet 中的過程:對于字符串 str,分別計算 h(1,str),h(2,str)…… h(k,str)。然后將 BitSet 的第 h(1,str)、h(2,str)…… h(k,str)位設為1。下圖是 Bloom Filter 加入字符串過程,很簡單吧?這樣就將字符串 str 映射到 BitSet 中的 k 個二進制位了。

  • (2) 檢查字符串是否存在的過程。下面是檢查字符串str是否被BitSet記錄過的過程:對于字符串 str,分別計算 h(1,str),h(2,str)…… h(k,str)。然后檢查 BitSet 的第 h(1,str)、h(2,str)…… h(k,str)位是否為1,若其中任何一位不為1則可以判定str一定沒有被記錄過。若全部位都是1,則 “認為” 字符串 str 存在。若一個字符串對應的 Bit 不全為1,則可以肯定該字符串一定沒有被 Bloom Filter 記錄過。(這是顯然的,因為字符串被記錄過,其對應的二進制位肯定全部被設為1了)。但是若一個字符串對應的Bit全為1,實際上是不能100%的肯定該字符串被 Bloom Filter 記錄過的。(因為有可能該字符串的所有位都剛好是被其他字符串所對應)這種將該字符串劃分錯的情況,稱為 false positive 。

三. Bloom Filter 參數選擇

  • (1) 哈希函數選擇。哈希函數的選擇對性能的影響應該是很大的,一個好的哈希函數要能近似等概率的將字符串映射到各個Bit。選擇k個不同的哈希函數比較麻煩,一種簡單的方法是選擇一個哈希函數,然后送入k個不同的參數。
  • (2) m,n,k 值,我們如何取值。我們定義:

    可能把不屬于這個集合的元素誤認為屬于這個集合(False Positive)

    不會把屬于這個集合的元素誤認為不屬于這個集合(False Negative)。

    哈希函數的個數 k、位數組大小 m、加入的字符串數量 n 的關系。哈希函數個數k取10,位數組大小m設為字符串個數 n 的20倍時,false positive 發生的概率是0.0000889 ,即10萬次的判斷中,會存在 9 次誤判,對于一天1億次的查詢,誤判的次數為9000次。

    哈希函數個數 k、位數組大小 m、加入的字符串數量 n 的關系可以參考參考文獻 (?http://pages.cs.wisc.edu/~cao/papers/summary-cache/node8.html?)。

Table 5:?False positive rate under various? m/ n?and? k?combinations.
m/nkk=17k=18k=19k=20k=21k=22k=23k=24
2215.22.67e-05???????
2315.91.61e-05???????
2416.69.84e-061e-05??????
2517.36.08e-066.11e-066.27e-06?????
26183.81e-063.76e-063.8e-063.92e-06????
2718.72.41e-062.34e-062.33e-062.37e-06????
2819.41.54e-061.47e-061.44e-061.44e-061.48e-06???
2920.19.96e-079.35e-079.01e-078.89e-078.96e-079.21e-07??
3020.86.5e-076e-075.69e-075.54e-075.5e-075.58e-07??
3121.54.29e-073.89e-073.63e-073.48e-073.41e-073.41e-073.48e-07?
3222.22.85e-072.55e-072.34e-072.21e-072.13e-072.1e-072.12e-072.17e-07

該文獻證明了對于給定的 m、n,當 k = ln(2)* m/n 時出錯的概率是最小的。(log2 e ≈ 1.44倍),同時該文獻還給出特定的k,m,n的出錯概率。例如:根據參考文獻1,哈希函數個數k取10,位數組大小m設為字符串個數n的20倍時,false positive 發生的概率是 0.0000889 ,這個概率基本能滿足網絡爬蟲的需求了。

四. Python 實現 Bloom filter

pybloomfiltermmap3? 和?pybloom 不同 的包。。。。。

Python3 安裝(?pybloomfiltermmap3 ):pip install pybloomfiltermmap3

  • pybloomfiltermmap3 github 地址:https://pypi.org/project/pybloomfiltermmap3/
  • pybloomfiltermmap3 官方文檔:https://pybloomfiltermmap3.readthedocs.io/en/latest/
  • pybloomfiltermmap 的 github:https://github.com/axiak/pybloomfiltermmap

pybloomfiltermmap3?is a Python 3 compatible fork of?pybloomfiltermmap?by?@axiak。pybloomfiltermmap3 的目標:在 python3 中為 bloom過濾器 提供一個快速、簡單、可伸縮、正確的庫。

Python 中文網:https://www.cnpython.com/pypi/pybloomfiltermmap3

#################################################################

Windows 安裝報錯解決方法:Python - 安裝pybloomfilter遇到的問題及解決辦法:https://blog.csdn.net/tianbianEileen/article/details/75059132

Stack Overflow 上的回答如下:
this problem looks like one “sys/mman.h:No such file or directory” And is a Unix header and is not available on Windows.
I suggest you should ues pybloom instead on windows:

pip install pybloom

通過 pypi?搜索發現,最新的??pybloom 是?pybloom3 0.0.3

pybloom 的 github 地址:https://github.com/Hexmagic/pybloom3

所以安裝命令是:pip install pybloom3

and you should use the package like this:

from pybloom import BloomFilter

#################################################################

pybloomfiltermmap3 快速示例:https://pybloomfiltermmap3.readthedocs.io/en/latest/

BloomFilter.copy_template(filename[, perm=0755]) → BloomFilter Creates a new BloomFilter object with the same parameters–same hash seeds, same size.. everything. Once this is performed, the two filters are comparable, so you can perform logical operators. Example:

>>> apple = BloomFilter(100, 0.1, '/tmp/apple') >>> apple.add('apple') False >>> pear = apple.copy_template('/tmp/pear') >>> pear.add('pear') False >>> pear |= apple

BloomFilter.len(item) → Integer Returns the number of distinct elements that have been added to the BloomFilter object, subject to the error given in error_rate.

>>> bf = BloomFilter(100, 0.1, '/tmp/fruit.bloom') >>> bf.add("Apple") >>> bf.add('Apple') >>> bf.add('orange') >>> len(bf) 2 >>> bf2 = bf.copy_template('/tmp/new.bloom') >>> bf2 |= bf >>> len(bf2) Traceback (most recent call last):... pybloomfilter.IndeterminateCountError: Length of BloomFilter object is unavailable after intersection or union called.

pybloom ?快速示例:

from pybloom import BloomFilter from pybloom import ScalableBloomFilterf = BloomFilter(capacity=1000, error_rate=0.001)print([f.add(x) for x in range(10)]) # [False, False, False, False, False, False, False, False, False, False]print(all([(x in f) for x in range(10)])) # Trueprint(10 in f) # Falseprint(5 in f) # Truef = BloomFilter(capacity=1000, error_rate=0.001) for i in range(0, f.capacity):_ = f.add(i) print((1.0 - (len(f) / float(f.capacity))) <= f.error_rate + 2e-18) # Truesbf = ScalableBloomFilter(mode=ScalableBloomFilter.SMALL_SET_GROWTH) count = 10000 for i in range(0, count):_ = sbf.add(i)print((1.0 - (len(sbf) / float(count))) <= sbf.error_rate + 2e-18) # True# len(sbf) may not equal the entire input length. 0.01% error is well # below the default 0.1% error threshold. As the capacity goes up, the # error will approach 0.1%.

五:Bloom Filter 的優缺點。

  • 優點:節約緩存空間(空值的映射),不再需要空值映射。減少數據庫或緩存的請求次數。提升業務的處理效率以及業務隔離性。
  • 缺點:存在誤判的概率。傳統的 Bloom Filter 不能作刪除操作。

六:Bloom-Filter 的應用場景

Bloom-Filter 一般用于在大數據量的集合中判定某元素是否存在。

  • (1) 適用于一些黑名單,垃圾郵件等的過濾,例如郵件服務器中的垃圾郵件過濾器。像網易,QQ這樣的公眾電子郵件(email)提供商,總是需要過濾來自發送垃圾郵件的人(spamer)的垃圾郵件。一個辦法就是記錄下那些發垃圾郵件的 email 地址。由于那些發送者不停地在注冊新的地址,全世界少說也有幾十億個發垃圾郵件的地址,將他們都存起來則需要大量的網絡服務器。如果用哈希表,每存儲一億個 email地址,就需要 1.6GB的內存(用哈希表實現的具體辦法是將每一個 email地址對應成一個八字節的信息指紋,然后將這些信息指紋存入哈希表,由于哈希表的存儲效率一般只有 50%,因此一個 email地址需要占用十六個字節。一億個地址大約要 1.6GB,即十六億字節的內存)。因此存貯幾十億個郵件地址可能需要上百 GB的內存。而 Bloom Filter 只需要哈希表 1/8 到 1/4 的大小就能解決同樣的問題。BloomFilter 決不會漏掉任何一個在黑名單中的可疑地址。而至于誤判問題,常見的補救辦法是在建立一個小的白名單,存儲那些可能別誤判的郵件地址。
  • (2) 在搜索引擎領域,Bloom-Filte r最常用于網絡蜘蛛(Spider)的 URL 過濾,網絡蜘蛛通常有一個 URL 列表,保存著將要下載和已經下載的網頁的 URL,網絡蜘蛛下載了一個網頁,從網頁中提取到新的 URL 后,需要判斷該 URL 是否已經存在于列表中。此時,Bloom-Filter 算法是最好的選擇。

Google 的 BigTable。 Google 的 BigTable 也使用了 Bloom Filter,以減少不存在的行或列在磁盤上的查詢,大大提高了數據庫的查詢操作的性能。

key-value 加快查詢。

一般 Bloom-Filter 可以與一些 key-value 的數據庫一起使用,來加快查詢。一般 key-value 存儲系統的 values 存在硬盤,查詢就是件費時的事。將 Storage 的數據都插入Filter,在 Filter 中查詢都不存在時,那就不需要去Storage 查詢了。當 False Position 出現時,只是會導致一次多余的Storage查詢。

由于 Bloom-Filter 所用空間非常小,所有 BF 可以常駐內存。這樣子的話對于大部分不存在的元素,只需要訪問內存中的 Bloom-Filter 就可以判斷出來了,只有一小部分,需要訪問在硬盤上的 key-value 數據庫。從而大大地提高了效率。如圖:

5. scrapy_redis 去重優化 (?7億數據 )

原文鏈接:https://blog.csdn.net/Bone_ACE/article/details/53099042

使用布隆去重代替scrapy_redis(分布式爬蟲)自帶的dupefilter:https://blog.csdn.net/qq_36574108/article/details/82889744

背景:

前些天接手了上一位同事的爬蟲,一個全網爬蟲,用的是 scrapy + redis 分布式,任務調度用的 scrapy_redis 模塊。

大家應該知道 scrapy 是默認開啟了去重的,用了 scrapy_redis 后去重隊列放在 redis 里面,爬蟲已經有7億多條URL的去重數據了,再加上一千多萬條 requests 的種子,redis 占用了160多G的內存(服務器,Centos7),總共才175G好么。去重占用了大部分的內存,不優化還能跑?

一言不合就用 Bloomfilter+Redis 優化了一下,內存占用立馬降回到了二十多G,保證漏失概率小于萬分之一的情況下可以容納50億條URL的去重,效果還是很不錯的!在此記錄一下,最后附上 Scrapy+Redis+Bloomfilter 去重的 Demo(可將去重隊列和種子隊列分開!),希望對使用 scrapy 框架的朋友有所幫助。

記錄:

我們要優化的是去重,首先剝絲抽繭查看框架內部是如何去重的。

  • 因為 scrapy_redis 會用自己 scheduler 替代 scrapy 框架的 scheduler 進行任務調度,所以直接去 scrapy_redis 模塊下查看scheduler.py 源碼即可。
  • 在 open() 方法中有句:self.df = load_object(self.dupefilter_cls).from_spider(spider),其中?load_object(self.dupefilter_cls) 是根據對象的絕對路徑而載入一個對象并返回,self.dupefilter_cls 就是?SCHEDULER_DUPEFILTER_CLASS = 'scrapy_redis.dupefilter.RFPDupeFilter',from_spider(spider) 是返回一個??RFPDupeFilter類 的實例。

    再看下面的 enqueue_request() 方法,

    里面有句?if not request.dont_filter and self.df.request_seen(request) ,self.df.request_seen()這就是用來去重的了。按住Ctrl再左鍵點擊request_seen查看它的代碼,可看到下面的代碼:

    首先得到一個 request 的指紋,然后使用 Redis 的 set 保存指紋??梢?scrapy_redis 是利用 set 數據結構來去重的,去重的對象是 request 的 fingerprint。至于這個 fingerprint 到底是什么,可以再深入去看 request_fingerprint() 方法的源碼(其實就是用 hashlib.sha1() 對 request 對象的某些字段信息進行壓縮)。我們用調試也可以看到,其實 fp 就是 request 對象加密壓縮后的一個字符串(40個字符,0~f)。

是否可用 Bloomfilter 進行優化?

以上步驟可以看出,我們只要在?request_seen()?方法上面動些手腳即可。由于現有的七億多去重數據存的都是這個 fingerprint,所有 Bloomfilter 去重的對象仍然是 request 對象的 fingerprint。更改后的代碼如下:

def request_seen(self, request):fp = request_fingerprint(request)if self.bf.isContains(fp): # 如果已經存在return Trueelse:self.bf.insert(fp)return False

self.bf 是類 Bloomfilter() 的實例化,關于這個Bloomfilter()類,看下面的?基于 Redis 的 Bloomfilter 去重

以上,優化的思路和代碼就是這樣;以下將已有的七億多的去重數據轉成 Bloomfilter 去重。

  • 內存將爆,動作稍微大點機器就能死掉,更別說Bloomfilter在上面申請內存了。當務之急肯定是將那七億多個fingerprint導出到硬盤上,而且不能用本機導,并且先要將redis的自動持久化給關掉。
  • 因為常用Mongo,所以習慣性首先想到Mongodb,從redis取出2000條再一次性插入Mongo,但速度還是不樂觀,瓶頸在于MongoDB。(猜測是MongoDB對_id的去重導致的,也可能是物理硬件的限制)
  • 后來想用SSDB,因為SSDB和Redis很相似,用list存肯定速度快很多。然而SSDB唯獨不支持Centos7,其他版本的系統都可。。
  • 最后才想起來用txt,這個最傻的方法,卻是非常有效的方法。速度很快,只是為了防止讀取時內存不足,每100萬個fingerprint存在了一個txt,四臺機器txt總共有七百個左右。
  • fingerprint取出來后redis只剩下一千多萬的Request種子,占用內存9G+。然后用Bloomfilter將txt中的fingerprint寫回Redis,寫完以后Redis占用內存25G,開啟redis自動持久化后內存占用49G左右。

6. 基于 Redis 的 Bloomfilter 去重

原文鏈接:http://blog.csdn.net/bone_ace/article/details/53107018

前言:

“去重” 是日常工作中會經常用到的一項技能,在爬蟲領域更是常用,并且規模一般都比較大。去重需要考慮兩個點:去重的數據量、去重速度。為了保持較快的去重速度,一般選擇在內存中進行去重。

  • 數據量不大時,可以直接放在內存里面進行去重,例如 python 可以使用 set() 進行去重。
  • 當去重數據需要持久化時可以使用 redis 的 set 數據結構。
  • 當數據量再大一點時,可以用不同的加密算法先將長字符串壓縮成 16/32/40 個字符,再使用上面兩種方法去重;
  • 當數據量達到億(甚至十億、百億)數量級時,內存有限,必須用 “位” 來去重,才能夠滿足需求。Bloomfilter 就是將去重對象映射到幾個內存“位”,通過幾個位的 0/1值來判斷一個對象是否已經存在。
  • 然而 Bloomfilter 運行在一臺機器的內存上,不方便持久化(機器 down 掉就什么都沒啦),也不方便分布式爬蟲的統一去重。如果可以在 Redis 上申請內存進行 Bloomfilter,以上兩個問題就都能解決了。

本文即是用 Python 基于 Redis 實現 Bloomfilter 去重。下面先放代碼,最后附上說明。

代碼:

# encoding=utf-8import redis from hashlib import md5class SimpleHash(object):def __init__(self, cap, seed):self.cap = capself.seed = seeddef hash(self, value):ret = 0for i in range(len(value)):ret += self.seed * ret + ord(value[i])return (self.cap - 1) & retclass BloomFilter(object):def __init__(self, host='localhost', port=6379, db=0, blockNum=1, key='bloomfilter'):""":param host: the host of Redis:param port: the port of Redis:param db: witch db in Redis:param blockNum: one blockNum for about 90,000,000; if you have more strings for filtering, increase it.:param key: the key's name in Redis"""self.server = redis.Redis(host=host, port=port, db=db)# Redis 的 String 類型最大容量為512M,現使用 256M= 2^8 * 2^20 字節 = 2^28 * 2^3 bitself.bit_size = 1 << 31 self.seeds = [5, 7, 11, 13, 31, 37, 61]self.key = keyself.blockNum = blockNumself.hashfunc = []for seed in self.seeds:self.hashfunc.append(SimpleHash(self.bit_size, seed))def isContains(self, str_input):if not str_input:return Falsem5 = md5()m5.update(str_input.encode("utf8"))str_input = m5.hexdigest()ret = Truename = self.key + str(int(str_input[0:2], 16) % self.blockNum)for f in self.hashfunc:loc = f.hash(str_input)ret = ret & self.server.getbit(name, loc)return retdef insert(self, str_input):m5 = md5()m5.update(str_input.encode("utf8"))str_input = m5.hexdigest()name = self.key + str(int(str_input[0:2], 16) % self.blockNum)for f in self.hashfunc:loc = f.hash(str_input)self.server.setbit(name, loc, 1)if __name__ == '__main__':""" 第一次運行時會顯示 not exists!,之后再運行會顯示 exists! """bf = BloomFilter()if bf.isContains('http://www.baidu.com'): # 判斷字符串是否存在print('exists!')else:print('not exists!')bf.insert('http://www.baidu.com')

說明:

  • Bloomfilter 算法如何使用位去重,這個百度上有很多解釋。簡單點說就是有幾個 seeds,現在申請一段內存空間,一個seed 可以和字符串哈希映射到這段內存上的一個位,幾個位都為1即表示該字符串已經存在。插入的時候也是,將映射出的幾個位都置為1。
  • 需要提醒一下的是 Bloomfilter 算法會有漏失概率,即不存在的字符串有一定概率被誤判為已經存在。這個概率的大小與seeds 的數量、申請的內存大小、去重對象的數量有關。下面有一張表,m 表示內存大小(多少個位),n 表示去重對象的數量,k 表示seed的個數。例如我代碼中申請了256M,即1<<31(m=2^31,約21.5億。即 256 * 1024 *1024 * 8),seed設置了7個??磌=7那一列,當漏失率為8.56e-05時,m/n值為23。所以n = 21.5/23 = 0.93(億),表示漏失概率為 8.56e-05 時,256M 內存可滿足0.93億條字符串的去重。同理當漏失率為 0.000112 時,256M內存可滿足 0.98 億條字符串的去重。

  • 基于 Redis 的 Bloomfilter 去重,其實就是利用了 Redis的String 數據結構,但 Redis 一個 String 最大只能 512M,所以如果去重的數據量大,需要申請多個去重塊(代碼中 blockNum 即表示去重塊的數量)。

    代碼中使用了 MD5 加密壓縮,將字符串壓縮到了 32 個字符(也可用 hashlib.sha1()壓縮成40個字符)。

    它有兩個作用,

    • 一是 Bloomfilter 對一個很長的字符串哈希映射的時候會出錯,經常誤判為已存在,壓縮后就不再有這個問題;

    • 二是壓縮后的字符為 0~f 共16中可能,我截取了前兩個字符,再根據blockNum將字符串指定到不同的去重塊進行去重。

    總結:

    基于 Redis 的 Bloomfilter 去重,既用上了 Bloomfilter 的海量去重能力,又用上了 Redis 的可持久化能力,基于 Redis 也方便分布式機器的去重。在使用的過程中,要預算好待去重的數據量,則根據上面的表,適當地調整 seed 的數量和 blockNum 數量(seed 越少肯定去重速度越快,但漏失率越大)。

    7. scrapy_redis 種子優化

    前言:

    繼?scrapy_redis去重優化(已有7億條數據)【?https://blog.csdn.net/bone_ace/article/details/53099042,優化去重之后,Redis 的內存消耗降了許多,然而還不滿足。這次對 scrapy_redis 的種子隊列作了一些優化(嚴格來說并不能用上“優化”這詞,其實就是結合自己的項目作了一些改進,對本項目能稱作優化,對 scrapy_redis 未必是個優化)。

    scrapy_redis 默認是將 Request 對象序列化后(變成一條字符串)存入 Redis 作為種子,需要的時候再取出來進行反序列化,還原成一個 Request 對象。

    現在的問題是:序列化后的字符串太長,短則幾百個字符,長則上千。我的爬蟲平時至少也要維護包含幾千萬種子的種子隊列,占用內存在20G~50G之間(Centos)。想要縮減種子的長度,這樣不僅 Redis 的內存消耗會降低,各個 slaver 從 Redis 拿種子的速度也會有所提高,從而整個分布式爬蟲系統的抓取速度也會有所提高(效果視具體情況而定,要看爬蟲主要阻塞在哪里)。

    記錄:

    1、首先看調度器,即 scrapy_redis 模塊下的 scheduler.py 文件,可以看到?enqueue_request()方法和?next_request()方法就是種子 入隊列出隊列 的地方,self.queue?指的是我們在 setting.py 里面設定的?SCHEDULER_QUEUE_CLASS?值,常用的是?'scrapy_redis.queue.SpiderPriorityQueue'。

    2、進入 scrapy_redis 模塊下的 queue.py 文件,SpiderPriorityQueue 類的代碼如下:

    class SpiderPriorityQueue(Base):"""Per-spider priority queue abstraction using redis' sorted set"""def __len__(self):"""Return the length of the queue"""return self.server.zcard(self.key)def push(self, request):"""Push a request"""data = self._encode_request(request)pairs = {data: -request.priority}self.server.zadd(self.key, **pairs)def pop(self, timeout=0):"""Pop a requesttimeout not support in this queue class"""pipe = self.server.pipeline()pipe.multi()pipe.zrange(self.key, 0, 0).zremrangebyrank(self.key, 0, 0)results, count = pipe.execute()if results:return self._decode_request(results[0])

    可以看到,上面用到了 Redis 的 zset 數據結構(它可以給種子加優先級),在進 Redis 之前用 _encode_request() 方法將Request 對象轉成字符串,_encode_request() 和 _decode_request 是 Base類下面的兩個方法:

    def _encode_request(self, request):"""Encode a request object"""return pickle.dumps(request_to_dict(request, self.spider), protocol=-1)def _decode_request(self, encoded_request):"""Decode an request previously encoded"""return request_from_dict(pickle.loads(encoded_request), self.spider)

    可以看到,這里先將 Request 對象轉成一個字典,再將字典序列化成一個字符串。Request 對象怎么轉成一個字典呢?看下面的代碼,一目了然。

    def request_to_dict(request, spider=None):"""Convert Request object to a dict.If a spider is given, it will try to find out the name of the spider methodused in the callback and store that as the callback."""cb = request.callbackif callable(cb):cb = _find_method(spider, cb)eb = request.errbackif callable(eb):eb = _find_method(spider, eb)d = {'url': to_unicode(request.url), # urls should be safe (safe_string_url)'callback': cb,'errback': eb,'method': request.method,'headers': dict(request.headers),'body': request.body,'cookies': request.cookies,'meta': request.meta,'_encoding': request._encoding,'priority': request.priority,'dont_filter': request.dont_filter,}return d

    調試截圖:(?注:d 為 Request 對象轉過來的字典,data 為字典序列化后的字符串。 )

    3、了解完 scrapy_redis 默認的種子處理方式,現在針對自己的項目作一些調整。我的是一個全網爬蟲,每個種子需要記錄的信息主要有兩個:url 和 callback 函數名。此時我們選擇不用序列化,直接用簡單粗暴的方式,將 callback 函數名和 url 拼接成一條字符串作為一條種子,這樣種子的長度至少會減少一半。另外我們的種子并不需要設優先級,所以也不用 zset 了,改用 Redis 的list。以下是我新建的 SpiderSimpleQueue 類,加在 queue.py 中。如果在 settings.py 里將

    SCHEDULER_QUEUE_CLASS?值設置成??'scrapy_redis.queue.SpiderSimpleQueue'?即可使用我這種野蠻粗暴的種子。

    from scrapy.utils.reqser import request_to_dict, request_from_dict, _find_methodclass SpiderSimpleQueue(Base):""" url + callback """def __len__(self):"""Return the length of the queue"""return self.server.llen(self.key)def push(self, request):"""Push a request"""url = request.urlcb = request.callbackif callable(cb):cb = _find_method(self.spider, cb)data = '%s--%s' % (cb, url)self.server.lpush(self.key, data)def pop(self, timeout=0):"""Pop a request"""if timeout > 0:data = self.server.brpop(self.key, timeout=timeout)if isinstance(data, tuple):data = data[1]else:data = self.server.rpop(self.key)if data:cb, url = data.split('--', 1)try:cb = getattr(self.spider, str(cb))return Request(url=url, callback=cb)except AttributeError:raise ValueError("Method %r not found in: %s" % (cb, self.spider))__all__ = ['SpiderQueue', 'SpiderPriorityQueue', 'SpiderSimpleQueue', 'SpiderStack']

    4、另外需要提醒的是,如果 scrapy 中加了中間件?process_request(),當 yield 一個 Request 對象的時候,scrapy_redis 會直接將它丟進 Redis 種子隊列,未執行?process_requset();需要一個 Request 對象的時候,scrapy_redis 會從 Redis 隊列中取出種子,此時才會處理?process_request()方法,接著去抓取網頁。
    所以并不需要擔心?process_request()里面添加的 Cookie 在 Redis 中放太久會失效,因為進 Redis 的時候它壓根都還沒執行process_request()。事實上 Request 對象序列化的時候帶上的字段很多都是沒用的默認字段,很多爬蟲都可以用 “callback+url” 的方式來優化種子。

    5、最后,在 Scrapy_Redis_Bloomfilter ( https://github.com/LiuXingMing/Scrapy_Redis_Bloomfilter)這個 demo 中我已作了修改,大家可以試試效果。

    結語:

    經過以上優化,Redis 的內存消耗從 42G 降到了 27G!里面包含7億多條種子的去重數據 和 4000W+ 條種子。并且六臺子爬蟲的抓取速度都提升了一些。

    兩次優化,內存消耗從160G+降到現在的27G,效果也是讓人滿意!

    原文鏈接:http://blog.csdn.net/bone_ace/article/details/53306629

    8. scrapy 引擎源碼解析

    本節內容將介紹下 scrapy 引擎具體實現的功能。 engine.py 提供了2個類:Slot 和 ExecutionEngine

    • Slot:? 提供了幾個方法,添加請求,刪除請求,關閉自己,觸發關閉方法。它使用 Twisted 的主循環 reactor 來不斷的調度執行 Engine 的 "_next_request" 方法,這個方法也是核心循環方法。
    • ExecutionEngine:? 引擎的執行任務 。

    爬蟲引擎控制調度器下載器? 爬蟲 的。 This is the Scrapy engine which controls the Scheduler, Downloader and Spiders. For more information see docs/topics/architecture.rst

    引擎 是 整個 scrapy 的核心控制和調度scrapy運行的。Engine 的 open_spider 方法完成了一些初始化,以及啟動調度器獲取種子隊列,以及去重隊列,最后調用 self._nest_request 開始一次爬取過程。

    open_spider 中 slot 調用 _next_request,接下來我們看看 _next_request ,先是通過 _needs_backout(spider) 判斷是否需要結束爬蟲,然后返回,然后通過 self._next_request_from_scheduler(spider) 方法判斷是否還有 URL 需要去爬。

    def _next_request(self, spider):slot = self.slotif not slot:returnif self.paused:return while not self._needs_backout(spider): # 是否需要返回if not self._next_request_from_scheduler(spider): # 是否還有 URL 需要爬取breakif slot.start_requests and not self._needs_backout(spider):try:request = next(slot.start_requests)except StopIteration:slot.start_requests = Noneexcept Exception:slot.start_requests = Nonelogger.error('Error while obtaining start requests',exc_info=True, extra={'spider': spider})else:self.crawl(request, spider)if self.spider_is_idle(spider) and slot.close_if_idle:self._spider_idle(spider)

    _next_request 循環通過 _next_request_from_scheduler(self,?spider) 方法從 scheduler 獲取下一個需要爬取的 request,然后送到下載器下載頁面。

    def _next_request_from_scheduler(self, spider):slot = self.slotrequest = slot.scheduler.next_request() # 從隊列獲取下一個待爬取的 requestif not request:returnd = self._download(request, spider) # 使用 download 下載 requestd.addBoth(self._handle_downloader_output, request, spider) # 輸出下載的 responsed.addErrback(lambda f: logger.info('Error while handling downloader output',exc_info=failure_to_exc_info(f),extra={'spider': spider}))d.addBoth(lambda _: slot.remove_request(request))d.addErrback(lambda f: logger.info('Error while removing request from slot',exc_info=failure_to_exc_info(f),extra={'spider': spider}))d.addBoth(lambda _: slot.nextcall.schedule())d.addErrback(lambda f: logger.info('Error while scheduling new request',exc_info=failure_to_exc_info(f),extra={'spider': spider}))return d

    繼續看?_download(request, spider) 函數

    ccdef _download(self, request, spider):slot = self.slotslot.add_request(request)def _on_success(response):assert isinstance(response, (Response, Request))if isinstance(response, Response): # 如果返回的是 Response 對象打印日志response.request = request # tie request to response receivedlogkws = self.logformatter.crawled(request, response, spider)logger.log(*logformatter_adapter(logkws), extra={'spider': spider})self.signals.send_catch_log(signal=signals.response_received, \response=response, request=request, spider=spider)return responsedef _on_complete(_):slot.nextcall.schedule()return _dwld = self.downloader.fetch(request, spider) # 使用downloader的fetch下載requestdwld.addCallbacks(_on_success) # 添加成功回掉方法dwld.addBoth(_on_complete)return dwld

    scrapy源碼分析 < 一 >:入口函數以及是如何運行

    運行 scrapy crawl example 命令的時候,就會執行我們寫的爬蟲程序。

    下面我們從源碼分析一下scrapy執行的流程:入口函數以及是如何運行:http://www.30daydo.com/article/530

    Scrapy 閱讀源碼分析

    原文鏈接:https://blog.csdn.net/weixin_37947156/category_6959928.html

    scrapy 命令

    當用 scrapy 寫好一個爬蟲后,使用?scrapy crawl <spider_name>命令就可以運行這個爬蟲,那么這個過程中到底發生了什么?

    scrapy?命令從何而來? 實際上,當你成功安裝 scrapy 后,使用如下命令,就能找到這個命令:

    $ which scrapy /usr/local/bin/scrapy

    使用?vim?或其他編輯器打開它:$ vim /usr/local/bin/scrapy 。其實它就是一個 python 腳本,而且代碼非常少。

    #!/usr/bin/python # -*- coding: utf-8 -*- import re import sys from scrapy.cmdline import execute if __name__ == '__main__': sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0]) sys.exit(execute())

    安裝 scrapy 后,為什么入口點是這里呢? 原因是在 scrapy 的安裝文件?setup.py?中,聲明了程序的入口處:

    from os.path import dirname, join from setuptools import setup, find_packageswith open(join(dirname(__file__), 'scrapy/VERSION'), 'rb') as f:version = f.read().decode('ascii').strip() setup(name='Scrapy',version=version,url='http://scrapy.org',description='A high-level Web Crawling and Screen Scraping framework',long_description=open('README.rst').read(),author='Scrapy developers',maintainer='Pablo Hoffman',maintainer_email='pablo@pablohoffman.com',license='BSD',packages=find_packages(exclude=('tests', 'tests.*')),include_package_data=True,zip_safe=False,entry_points={'console_scripts': ['scrapy = scrapy.cmdline:execute']},classifiers=['Framework :: Scrapy','Development Status :: 5 - Production/Stable','Environment :: Console','Intended Audience :: Developers','License :: OSI Approved :: BSD License','Operating System :: OS Independent','Programming Language :: Python','Programming Language :: Python :: 2','Programming Language :: Python :: 2.7','Topic :: Internet :: WWW/HTTP','Topic :: Software Development :: Libraries :: Application Frameworks','Topic :: Software Development :: Libraries :: Python Modules',],install_requires=['Twisted>=10.0.0','w3lib>=1.8.0','queuelib','lxml','pyOpenSSL','cssselect>=0.9','six>=1.5.2',], )

    entry_points?指明了入口是?cmdline.py?的?execute?方法,在安裝過程中,setuptools?這個包管理工具,就會把上述那一段代碼生成放在可執行路徑下。

    入口(execute.py)

    既然現在已經知道了 scrapy 的入口是?scrapy/cmdline.py?的?execute?方法,我們來看一下這個方法。

    def execute(argv=None, settings=None):if argv is None:argv = sys.argvif settings is None:settings = get_project_settings()# set EDITOR from environment if availabletry:editor = os.environ['EDITOR']except KeyError:passelse:settings['EDITOR'] = editorinproject = inside_project()cmds = _get_commands_dict(settings, inproject)cmdname = _pop_command_name(argv)parser = optparse.OptionParser(formatter=optparse.TitledHelpFormatter(),conflict_handler='resolve')if not cmdname:_print_commands(settings, inproject)sys.exit(0)elif cmdname not in cmds:_print_unknown_command(settings, cmdname, inproject)sys.exit(2)cmd = cmds[cmdname]parser.usage = "scrapy %s %s" % (cmdname, cmd.syntax())parser.description = cmd.long_desc()settings.setdict(cmd.default_settings, priority='command')cmd.settings = settingscmd.add_options(parser)opts, args = parser.parse_args(args=argv[1:])_run_print_help(parser, cmd.process_options, args, opts)cmd.crawler_process = CrawlerProcess(settings)_run_print_help(parser, _run_command, cmd, args, opts)sys.exit(cmd.exitcode)

    函數主要是初始化項目配置,在函數最后是初始化?CrawlerProcess?實例,然后運行對應命令實例的run方法。如果運行命令是scrapy crawl <spider_name>,則運行的就是?commands/crawl.py?的?run:

    run方法中調用了?CrawlerProcess?實例的?crawl?和?start,就這樣整個爬蟲程序就會運行起來了。

    再來看?CrawlerProcess 初始化。scrapy.core.engine.py( 其他代碼省略。。。?):

    class CrawlerProcess(CrawlerRunner):def __init__(self, settings=None, install_root_handler=True):super(CrawlerProcess, self).__init__(settings)install_shutdown_handlers(self._signal_shutdown)configure_logging(self.settings, install_root_handler)log_scrapy_info(self.settings)

    構造方法中調用了父類?CrawlerRunner?的構造:

    class CrawlerRunner:def __init__(self, settings=None):if isinstance(settings, dict) or settings is None:settings = Settings(settings)self.settings = settings# 獲取爬蟲加載器self.spider_loader = self._get_spider_loader(settings)self._crawlers = set()self._active = set()self.bootstrap_failed = Falseself._handle_twisted_reactor()

    初始化時,調用了?_get_spider_loader?方法:

    默認配置文件中的?spider_loader?配置的是 scrapy.spiderloader.SpiderLoader:

    爬蟲加載器會加載所有的爬蟲腳本,最后生成一個{spider_name: spider_cls}的字典。

    執行 crawl 和 start 方法

    CrawlerProcess?初始化完之后,調用?crawl方法:

    這個過程會創建?Cralwer實例,然后調用它的?crawl方法,最后調用?start方法:

    reactor?是個什么東西呢?它是?Twisted模塊的事件管理器,只要把需要執行的事件方法注冊到reactor中,然后調用它的run方法,它就會幫你執行注冊好的事件方法,如果遇到網絡IO等待,它會自動幫你切換可執行的事件方法,非常高效。

    大家不用在意reactor是如何工作的,你可以把它想象成一個線程池,只是采用注冊回調的方式來執行事件。

    到這里,爬蟲的之后調度邏輯就交由引擎ExecuteEngine處理了。

    scrapy 源碼分析( 系列?):https://blog.csdn.net/happyAnger6/category_6085726_2.html

    scrapy 是一個基于 twisted 實現的開源爬蟲,要讀懂其源碼,需要對twisted的異步編程模型有一定了解??梢酝ㄟ^之前3篇deferred的相關教程了解。

    下面是總結的執行一個爬蟲任務的整體執行流程,請將圖片放大查看,即運行"scrapy crawl? xxxSpider"的執行流程:

    流程中主要的顏色框的含義如下 :

    • 1.紅色框是模塊或者類。
    • 2.紫色框是向模塊或者類發送的消息,一般為函數調用。
    • 3.紅色框垂直以下的黑色框即為本模塊或者對象執行流程的偽代碼描述。

    幾個關鍵的模塊和類介紹如下:

    • cmdline:命令行執行模塊,主要用于配置的獲取,并執行相應的ScrapyCommand。
    • ScrapyCommand:命令對象,用于執行不同的命令。對于crawl任務,主要是調用CrawlerProcess的crawl和start方法。
    • CrawlerProcess:顧名思義,爬取進程,主要用于管理Crawler對象,可以控制多個Crawler對象來同時進行多個不同的爬取任務,并調用Crawler的crawl方法。
    • Crawler:爬取對象,用來控制爬蟲的執行,里面會通過一個執行引擎engine對象來控制spider從打開到啟動等生命周期。
    • ExecutionEngine:執行引擎,主要控制整個調度過程,通過twisted的task.LoopingCall來不斷的產生爬取任務。

    scrapy 源碼解析

    <scrapy>scrapy源碼剖析https://www.cnblogs.com/shuimohei/p/13363462.html

    scrapy 源碼解析 (一):啟動流程源碼分析(一)命令行啟動:https://www.cnblogs.com/qiu-hua/p/12930422.html
    scrapy 源碼解析 (二):啟動流程源碼分析(二) CrawlerProcess 主進程:https://www.cnblogs.com/qiu-hua/p/12930707.html
    scrapy 源碼解析 (三):啟動流程源碼分析(三) ExecutionEngine 執行引擎:https://www.cnblogs.com/qiu-hua/p/12930803.html
    scrapy 源碼解析 (四):啟動流程源碼分析(四) Scheduler調度器:https://www.cnblogs.com/qiu-hua/p/12932254.html
    scrapy 源碼解析 (五):啟動流程源碼分析(五) Scraper刮取器:https://www.cnblogs.com/qiu-hua/p/12932818.html

    Python 之 Scrapy 框架源碼解析:https://blog.csdn.net/cui_yonghua/article/details/107040329

    scrapy 信號

    官網說明:https://docs.scrapy.org/en/latest/topics/signals.html

    scrapy 基礎組件專題(四):信號運用:https://www.cnblogs.com/qiu-hua/p/12638683.html

    scrapy 的信號(signal)以及對下載中間件的一些總結:https://blog.csdn.net/fiery_heart/article/details/82229871

    9. DNS 解析緩存

    原文鏈接:https://blog.csdn.net/bone_ace/article/details/55000101

    前言:

    這是 Python 爬蟲中 DNS 解析緩存模塊中的核心代碼,是去年的代碼了,現在放出來 有興趣的可以看一下。
    一般一個域名的 DNS 解析時間在 10~60 毫秒之間,這看起來是微不足道,但是對于大型一點的爬蟲而言這就不容忽視了。例如我們要爬新浪微博,同個域名下的請求有1千萬(這已經不算多的了),那么耗時在 10~60 萬秒之間,一天才 86400 秒。也就是說單 DNS 解析這一項就用了好幾天時間,此時加上 DNS 解析緩存,效果就明顯了。

    下面直接放代碼,說明在后面。

    代碼:

    # encoding=utf-8 # --------------------------------------- # 版本:0.1 # 日期:2016-04-26 # 作者:九茶<bone_ace@163.com> # 開發環境:Win64 + Python 2.7 # ---------------------------------------import socket # from gevent import socket_dnscache = {}def _setDNSCache():""" DNS緩存 """def _getaddrinfo(*args, **kwargs):if args in _dnscache:# print str(args) + " in cache"return _dnscache[args]else:# print str(args) + " not in cache"_dnscache[args] = socket._getaddrinfo(*args, **kwargs)return _dnscache[args]if not hasattr(socket, '_getaddrinfo'):socket._getaddrinfo = socket.getaddrinfosocket.getaddrinfo = _getaddrinfo

    說明:

    其實也沒什么難度,就是將 socket 里面的緩存保存下來,避免重復獲取。可以將上面的代碼放在一個 dns_cache.py 文件里,爬蟲框架里調用一下這個?_setDNSCache()方法就行了。

    需要說明一下的是,如果你使用了 gevent 協程,并且用上了 monkey.patch_all(),要注意此時爬蟲已經改用 gevent 里面的socket 了,DNS 解析緩存模塊也應該要用 gevent 的 socket 才行。

    10. Scrapy cookies 淺析

    首先打消大家的疑慮,?Scrapy 會自動管理 cookies,?就像瀏覽器一樣:

    Does Scrapy manage cookies automatically?

    Yes, Scrapy receives and keeps track of cookies sent by servers, and sends them back on subsequent requests, like any regular web browser does.

    Cookies 的管理是通過 CookiesMiddleware,?它屬于 DownloadMiddleware 的一部分,所有的 requests 和 response 都要經過它的處理。

    首先看下處理 request 的部分,代碼如下:

    class CookiesMiddleware(object):"""This middleware enables working with sites that need cookies"""def __init__(self, debug=False):# 用字典生成多個cookiesjarself.jars = defaultdict(CookieJar)self.debug = debugdef process_request(self, request, spider):if request.meta.get('dont_merge_cookies', False):return# 每個cookiesjar的key都存儲在 meta字典中cookiejarkey = request.meta.get("cookiejar")jar = self.jars[cookiejarkey]cookies = self._get_request_cookies(jar, request)# 把requests的cookies存儲到cookiesjar中for cookie in cookies:jar.set_cookie_if_ok(cookie, request)# set Cookie header# 刪除原有的cookiesrequest.headers.pop('Cookie', None)# 添加cookiesjar中的cookies到requests headerjar.add_cookie_header(request)self._debug_cookie(request, spider)

    流程如下:

    • 使用字典初始化多個 cookies jar
    • 把每個 requests 指定的 cookies jar 提取出來
    • 然后根據 policy 把 requests 中的 cookies 添加 cookies jar
    • 最后把 cookies jar 中合適的 cookies 添加到 requests 首部

    接下來看看如何處理 response 中的 cookies:

    def process_response(self, request, response, spider):if request.meta.get('dont_merge_cookies', False):return response# extract cookies from Set-Cookie and drop invalid/expired cookiescookiejarkey = request.meta.get("cookiejar")jar = self.jars[cookiejarkey]jar.extract_cookies(response, request)self._debug_set_cookie(response, spider)return response

    流程如下:

    • 首先從 cookies jar 字典中把 requests 對應的 cookiesjar 提取出來.
    • 使用 extract_cookies 把 response 首部中的 cookies 添加到 cookies jar

    11. 擴展部分

    python 之 goose3 庫?--- 文章提取工具

    github 地址:https://github.com/goose3/goose3

    goose3 官網文檔:https://goose3.readthedocs.io/en/latest/

    goose3 是什么?

    GOOSE3 最初是用 Java 編寫的一篇文章提取器,最近將它(Auff2011)轉換成Scala項目,這是 python 中的完全重寫。該軟件的目標是獲取任何新聞文章或文章類型的網頁,不僅提取文章的主體,而且還提取所有元數據和圖片。

    官方網站:https://github.com/goose3/goose3

    安裝

    • pip install goose3
    • mkvirtualenv --no-site-packages goose3 git clone https://github.com/goose3/goose3.git cd goose3 pip install -r ./requirements/python python setup.py install

    使用:

    示例用法:https://pypi.org/project/goose3/3.0.4/

    python 之 goose3 庫:https://blog.csdn.net/weixin_42547344/article/details/100735035

    動手實踐 CURL

    CURL 是利用 URL 語法在命令行方式下工作的開源文件傳輸工具。它支持http、https、ftp、ftps、telnet 等多種協議,常被用來抓取網頁和監控Web服務器狀態。

    CURL 使用

    curl 命令可以用來構造http請求。
    通用語法:curl [option] [URL...]

    使用實例

    curl 是 Linux下一個很強大的 http 命令行工具,其功能十分強大。

    基本用法

    curl http://www.baidu.com

    抓取 www.ip138.com 查詢網: 如發現亂碼,可以使用iconv轉碼:

    curl http://ip138.com|iconv -f gb2312

    回車之后,html顯示在屏幕上了 ~

    1.1 get方式提交數據:

    curl -G -d "name=value&name2=value2" http://www.baidu.com

    1.2 post方式提交數據:

    curl -d "name=value&name2=value2" http://www.baidu.com #post數據 curl -d a=b&c=d&txt@/tmp/txt http://www.baidu.com #post文件

    以表單的方式上傳文件:

    curl -F file=@/tmp/me.txt http://www.aiezu.com

    相當于設置form表單的method="POST"和enctype='multipart/form-data'兩個屬性。

    保存訪問的網頁

    curl http://www.baidu.com > page.html

    或者用 curl 的內置 option 就好,存下 http 的結果,用這個 option: -o

    curl -o page.html http://www.baidu.com curl -O http://sh.meituan.com/shop/42030772% Total % Received % Xferd Average Speed Time Time Time CurrentDload Upload Total Spent Left Speed 100 159k 0 159k 0 0 328k 0 --:--:-- --:--:-- --:--:-- 328k

    下載過程中標準輸出還會顯示下載的統計信息,比如進度、下載字節數、下載速度等

    這樣,自動保存文件42030772,看到屏幕上出現一個下載頁面進度指示。顯示100%則表示保存成功

    設置 Header

    curl -H 'Host: 157.166.226.25'-H 'Accept-Language: es'-H 'Cookie: ID=1234' http://cnn.com

    顯示文檔信息

    -I:顯示文檔信息

    curl -I http://www.sina.com.cn/ -H Accept-Encoding:gzip,defalte

    指定proxy服務器以及其端口

    -x :可以指定http訪問所使用的proxy服務器及其端口

    curl -x 123.45.67.89:1080 -o page.html http://www.linuxidc.com curl -x http://username:pwd@ip:port http://www.baidu.com

    使用cookie

    有些網站是使用cookie來記錄session信息。對于chrome這樣的瀏覽器,可以輕易處理cookie信息,但在curl中只要增加相關參數也是可以很容易的處理cookie

    -c: 保存http的response里面的cookie信息。

    curl -c cookiec.txt http://www.baidu.com

    執行后cookie信息就被存到了cookiec.txt里面了

    -D: 保存http的response里面的header信息

    curl -D cookied.txt http://www.baidu.com

    執行后cookie信息就被存到了cookied.txt里面了
    注意:-c(小寫)產生的cookie和-D里面的cookie是不一樣的。

    -b:使用cookie

    很多網站都是通過監視你的cookie信息來判斷你是否按規矩訪問他們的網站的,因此我們需要使用保存的cookie信息。

    curl -b cookiec.txt http://www.baidu.com

    模仿瀏覽器信息

    有些網站需要使用特定的瀏覽器去訪問他們,有些還需要使用某些特定的版本。

    -A :指定瀏覽器去訪問網站

    curl -A "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 5.0)" http://www.baidu.com

    這樣服務器端就會認為是使用IE8.0去訪問的

    偽造referer(盜鏈)

    很多服務器會檢查http訪問的referer從而來控制訪問。比如:你是先訪問首頁,然后再訪問首頁中的郵箱頁面,這里訪問郵箱的referer地址就是訪問首頁成功后的頁面地址,如果服務器發現對郵箱頁面訪問的referer地址不是首頁的地址,就斷定那是個盜連了

    -e:設定referer

    curl -e "www.baidu.com" http://news.baidu.com/

    這樣就會讓服務器其以為你是從www.baidu.com點擊某個鏈接過來的

    下載文件

    9.1 -o/-O文件下載

    -o: 把輸出寫到該文件中

    curl -o dodo1.jpg http://www.shaimn.com/uploads/allimg/160613/1-160613121111.jpg

    -O:把輸出寫到該文件中,保留遠程文件的文件名

    curl -O http://www.shaimn.com/uploads/allimg/160613/1-160613121111.jpg

    這樣就會以服務器上的名稱保存文件到本地

    9.2 循環下載

    有時候下載圖片可以能是前面的部分名稱是一樣的,就最后的尾椎名不一樣

    curl -O http://www.shaimn.com/uploads/allimg/160613/1-16061312111[1-5].jpg

    這樣就會把
    1-16061312111.jpg、
    1-16061312112.jpg、
    1-16061312113.jpg、
    1-16061312114.jpg、
    1-16061312115.jpg 全部保存下來

    9.3 下載重命名

    curl http://www.shaimn.com/uploads/allimg/160613/1-16061312111[1-5].jpg -o dodo#1.jpg

    dodo1.jpg,dodo2.jpg,dodo3.jpg,dodo4.jpg,dodo5.jpg

    9.4 分塊下載

    有時候下載的東西會比較大,這個時候我們可以分段下載。使用內置option:-r

    curl -r 0-100 -o dodo1_part1.JPG http://www.shaimn.com/uploads/allimg/160613/1-160613121111.jpg curl -r 100-200 -o dodo1_part2.JPG http://www.shaimn.com/uploads/allimg/160613/1-160613121111.jpg curl -r 200- -o dodo1_part3.JPG http://www.shaimn.com/uploads/allimg/160613/1-160613121111.jpg cat dodo1_part* > dodo1.JPG

    這樣就可以查看dodo1.JPG的內容了

    9.5 通過ftp下載文件

    curl可以通過ftp下載文件,curl提供兩種從ftp中下載的語法

    curl -O -u 用戶名:密碼 ftp://www.linux.com/dodo1.JPG curl -O ftp://用戶名:密碼@www.linux.com/dodo1.JPG

    9.6 顯示下載進度條

    curl -# -O http://www.linux.com/dodo1.JPG

    9.7:不會顯示下載進度信息

    curl -s -O http://www.linux.com/dodo1.JPG

    斷點續傳

    在windows中,我們可以使用迅雷這樣的軟件進行斷點續傳。

    curl可以通過內置option:-C同樣可以達到相同的效果
    如果在下載dodo1.JPG的過程中突然掉線了,可以使用以下的方式續傳

    curl -C -O http://www.linux.com/dodo1.JPG通過使用-C選項可對大文件使用斷點續傳功能,如:# 當文件在下載完成之前結束該進程 curl -O http://www.gnu.org/software/gettext/manual/gettext.html ############## 20.1%# 通過添加-C選項繼續對該文件進行下載,已經下載過的文件不會被重新下載 curl -C - -O http://www.gnu.org/software/gettext/manual/gettext.html ############### 21.1%

    上傳文件

    curl不僅僅可以下載文件,還可以上傳文件。通過內置option:-T來實現

    # curl -T dodo1.JPG -u 用戶名:密碼 ftp://www.linux.com/img/

    這樣就向ftp服務器上傳了文件dodo1.JPG

    顯示抓取錯誤

    # curl -f http://www.linux.com/error

    對 CURL 使用網絡限速

    通過--limit-rate選項對CURL的最大網絡使用進行限制

    下載速度最大不會超過1000B/secondcurl --limit-rate 1000B -O http://www.gnu.org/software/gettext/manual/gettext.html

    linux curl 命令

    -a/--append 上傳文件時,附加到目標文件 -A/--user-agent <string> 設置用戶代理發送給服務器 - anyauth 可以使用“任何”身份驗證方法 -b/--cookie <name=string/file> cookie字符串或文件讀取位置 - basic 使用HTTP基本驗證 -B/--use-ascii 使用ASCII /文本傳輸 -c/--cookie-jar <file> 操作結束后把cookie寫入到這個文件中 -C/--continue-at <offset> 斷點續轉 -d/--data <data> HTTP POST方式傳送數據 --data-ascii <data> 以ascii的方式post數據 --data-binary <data> 以二進制的方式post數據 --negotiate 使用HTTP身份驗證 --digest 使用數字身份驗證 --disable-eprt 禁止使用EPRT或LPRT --disable-epsv 禁止使用EPSV -D/--dump-header <file> 把header信息寫入到該文件中 --egd-file <file> 為隨機數據(SSL)設置EGD socket路徑 --tcp-nodelay 使用TCP_NODELAY選項 -e/--referer 來源網址 -E/--cert <cert[:passwd]> 客戶端證書文件和密碼 (SSL) --cert-type <type> 證書文件類型 (DER/PEM/ENG) (SSL) --key <key> 私鑰文件名 (SSL) --key-type <type> 私鑰文件類型 (DER/PEM/ENG) (SSL) --pass <pass> 私鑰密碼 (SSL) --engine <eng> 加密引擎使用 (SSL). "--engine list" for list --cacert <file> CA證書 (SSL) --capath <directory> CA目錄 (made using c_rehash) to verify peer against (SSL) --ciphers <list> SSL密碼 --compressed 要求返回是壓縮的形勢 (using deflate or gzip) --connect-timeout <seconds> 設置最大請求時間 --create-dirs 建立本地目錄的目錄層次結構 --crlf 上傳是把LF轉變成CRLF -f/--fail 連接失敗時不顯示http錯誤 --ftp-create-dirs 如果遠程目錄不存在,創建遠程目錄 --ftp-method [multicwd/nocwd/singlecwd] 控制CWD的使用 --ftp-pasv 使用 PASV/EPSV 代替端口 --ftp-skip-pasv-ip 使用PASV的時候,忽略該IP地址 --ftp-ssl 嘗試用 SSL/TLS 來進行ftp數據傳輸 --ftp-ssl-reqd 要求用 SSL/TLS 來進行ftp數據傳輸 -F/--form <name=content> 模擬http表單提交數據 -form-string <name=string> 模擬http表單提交數據 -g/--globoff 禁用網址序列和范圍使用{}和[] -G/--get 以get的方式來發送數據 -h/--help 幫助 -H/--header <line>自定義頭信息傳遞給服務器 --ignore-content-length 忽略的HTTP頭信息的長度 -i/--include 輸出時包括protocol頭信息 -I/--head 只顯示文檔信息 從文件中讀取-j/--junk-session-cookies忽略會話Cookie - 界面<interface>指定網絡接口/地址使用 - krb4 <級別>啟用與指定的安全級別krb4 -j/--junk-session-cookies 讀取文件進忽略session cookie --interface <interface> 使用指定網絡接口/地址 --krb4 <level> 使用指定安全級別的krb4 -k/--insecure 允許不使用證書到SSL站點 -K/--config 指定的配置文件讀取 -l/--list-only 列出ftp目錄下的文件名稱 --limit-rate <rate> 設置傳輸速度 --local-port<NUM> 強制使用本地端口號 -m/--max-time <seconds> 設置最大傳輸時間 --max-redirs <num> 設置最大讀取的目錄數 --max-filesize <bytes> 設置最大下載的文件總量 -M/--manual 顯示全手動 -n/--netrc 從netrc文件中讀取用戶名和密碼 --netrc-optional 使用 .netrc 或者 URL來覆蓋-n --ntlm 使用 HTTP NTLM 身份驗證 -N/--no-buffer 禁用緩沖輸出 -o/--output 把輸出寫到該文件中 -O/--remote-name 把輸出寫到該文件中,保留遠程文件的文件名 -p/--proxytunnel 使用HTTP代理 --proxy-anyauth 選擇任一代理身份驗證方法 --proxy-basic 在代理上使用基本身份驗證 --proxy-digest 在代理上使用數字身份驗證 --proxy-ntlm 在代理上使用ntlm身份驗證 -P/--ftp-port <address> 使用端口地址,而不是使用PASV -Q/--quote <cmd>文件傳輸前,發送命令到服務器 -r/--range <range>檢索來自HTTP/1.1或FTP服務器字節范圍 --range-file 讀取(SSL)的隨機文件 -R/--remote-time 在本地生成文件時,保留遠程文件時間 --retry <num> 傳輸出現問題時,重試的次數 --retry-delay <seconds> 傳輸出現問題時,設置重試間隔時間 --retry-max-time <seconds> 傳輸出現問題時,設置最大重試時間 -s/--silent靜音模式。不輸出任何東西 -S/--show-error 顯示錯誤 --socks4 <host[:port]> 用socks4代理給定主機和端口 --socks5 <host[:port]> 用socks5代理給定主機和端口 --stderr <file> -t/--telnet-option <OPT=val> Telnet選項設置 --trace <file> 對指定文件進行debug --trace-ascii <file> Like --跟蹤但沒有hex輸出 --trace-time 跟蹤/詳細輸出時,添加時間戳 -T/--upload-file <file> 上傳文件 --url <URL> Spet URL to work with -u/--user <user[:password]>設置服務器的用戶和密碼 -U/--proxy-user <user[:password]>設置代理用戶名和密碼 -v/--verbose -V/--version 顯示版本信息 -w/--write-out [format]什么輸出完成后 -x/--proxy <host[:port]>在給定的端口上使用HTTP代理 -X/--request <command>指定什么命令 -y/--speed-time 放棄限速所要的時間。默認為30 -Y/--speed-limit 停止傳輸速度的限制,速度時間'秒 -z/--time-cond 傳送時間設置 -0/--http1.0 使用HTTP 1.0 -1/--tlsv1 使用TLSv1(SSL) -2/--sslv2 使用SSLv2的(SSL) -3/--sslv3 使用的SSLv3(SSL) --3p-quote like -Q for the source URL for 3rd party transfer --3p-url 使用url,進行第三方傳送 --3p-user 使用用戶名和密碼,進行第三方傳送 -4/--ipv4 使用IP4 -6/--ipv6 使用IP6 -#/--progress-bar 用進度條顯示當前的傳送狀態

    一些常見的限制方式

    上述都是講的都是一些的基礎的知識,現在我就列一些比較常見的限制方式,如何突破這些限制抓取數據。

    Basic Auth 一般會有用戶授權的限制,會在headers的Autheration字段里要求加入;

    Referer 通常是在訪問鏈接時,必須要帶上Referer字段,服務器會進行驗證,例如抓取京東的評論;

    User-Agent 會要求真是的設備,如果不加會用編程語言包里自有User-Agent,可以被辨別出來;

    Cookie 一般在用戶登錄或者某些操作后,服務端會在返回包中包含Cookie信息要求瀏覽器設置Cookie,沒有Cookie會很容易被辨別出來是偽造請求;

    也有本地通過JS,根據服務端返回的某個信息進行處理生成的加密信息,設置在Cookie里面;

    Gzip 請求headers里面帶了gzip,返回有時候會是gzip壓縮,需要解壓;

    JavaScript 加密操作 一般都是在請求的數據包內容里面會包含一些被javascript進行加密限制的信息,例如新浪微博會進行SHA1和RSA加密,之前是兩次SHA1加密,然后發送的密碼和用戶名都會被加密;

    其他字段 因為http的headers可以自定義地段,所以第三方可能會加入了一些自定義的字段名稱或者字段值,這也是需要注意的。

    真實的請求過程中,其實不止上面某一種限制,可能是幾種限制組合在一次,比如如果是類似RSA加密的話,可能先請求服務器得到Cookie,然后再帶著Cookie去請求服務器拿到公鑰,然后再用js進行加密,再發送數據到服務器。所以弄清楚這其中的原理,并且耐心分析很重要。

    防封禁策略

    Scrapy:

    http://doc.scrapy.org/en/master/topics/practices.html#avoiding-getting-banned

    如何讓你的 scrapy 爬蟲不再被 ban

    根據 scrapy 官方文檔:https://docs.scrapy.org/en/master/topics/practices.html#avoiding-getting-banned?里面的描述,要防止 scrapy 被 ban,主要有以下幾個策略。

    • 動態設置 user agent
    • 禁用 cookies
    • 設置延遲下載
    • 使用?Google cache
    • 使用IP地址池(Tor project、VPN和代理IP)
    • 使用?Crawlera

    由于 Google cache 受國內網絡的影響,你懂得; 所以主要從動態隨機設置user agent、禁用cookies、設置延遲下載和使用代理IP這幾個方式。

    本文以?cnblogs 為例

    創建 middlewares.py

    scrapy代理IP、user agent 的切換都是通過 DOWNLOADER_MIDDLEWARES 進行控制,下面我們創建 middlewares.py文件。

    [root@bogon cnblogs]# vi cnblogs/middlewares.py

    如下內容:

    import random import base64 from settings import PROXIESclass RandomUserAgent(object):"""Randomly rotate user agents based on a list of predefined ones"""def __init__(self, agents):self.agents = agents@classmethoddef from_crawler(cls, crawler):return cls(crawler.settings.getlist('USER_AGENTS'))def process_request(self, request, spider):#print "**************************" + random.choice(self.agents)request.headers.setdefault('User-Agent', random.choice(self.agents))class ProxyMiddleware(object):def process_request(self, request, spider):proxy = random.choice(PROXIES)if proxy['user_pass'] is not None:#request.meta['proxy'] = "http://YOUR_PROXY_IP:PORT"request.meta['proxy'] = "http://%s" % proxy['ip_port']#proxy_user_pass = "USERNAME:PASSWORD"encoded_user_pass = base64.encodestring(proxy['user_pass'])request.headers['Proxy-Authorization'] = 'Basic ' + encoded_user_passprint "**************ProxyMiddleware have pass************" + proxy['ip_port']else:print "**************ProxyMiddleware no pass************" + proxy['ip_port']request.meta['proxy'] = "http://%s" % proxy['ip_port']

    類 RandomUserAgent 主要用來動態獲取 user agent,user agent 列表 USER_AGENTS 在 settings.py 中進行配置。

    類 ProxyMiddleware 用來切換代理,proxy 列表 PROXIES 也是在 settings.py 中進行配置。

    如果你用的是 socks5 代理,那么對不起,目前 scrapy 還不能直接支持,可以通過 Privoxy 等軟件將其本地轉化為 http 代理

    修改 settings.py 配置 USER_AGENTS 和 PROXIES

    USER_AGENTS = ["Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; AcooBrowser; .NET CLR 1.1.4322; .NET CLR 2.0.50727)","Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0; Acoo Browser; SLCC1; .NET CLR 2.0.50727; Media Center PC 5.0; .NET CLR 3.0.04506)","Mozilla/4.0 (compatible; MSIE 7.0; AOL 9.5; AOLBuild 4337.35; Windows NT 5.1; .NET CLR 1.1.4322; .NET CLR 2.0.50727)","Mozilla/5.0 (Windows; U; MSIE 9.0; Windows NT 9.0; en-US)","Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Win64; x64; Trident/5.0; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 2.0.50727; Media Center PC 6.0)","Mozilla/5.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0; WOW64; Trident/4.0; SLCC2; .NET CLR 2.0.50727; .NET CLR 3.5.30729; .NET CLR 3.0.30729; .NET CLR 1.0.3705; .NET CLR 1.1.4322)","Mozilla/4.0 (compatible; MSIE 7.0b; Windows NT 5.2; .NET CLR 1.1.4322; .NET CLR 2.0.50727; InfoPath.2; .NET CLR 3.0.04506.30)","Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN) AppleWebKit/523.15 (KHTML, like Gecko, Safari/419.3) Arora/0.3 (Change: 287 c9dfb30)","Mozilla/5.0 (X11; U; Linux; en-US) AppleWebKit/527+ (KHTML, like Gecko, Safari/419.3) Arora/0.6","Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8.1.2pre) Gecko/20070215 K-Ninja/2.1.1","Mozilla/5.0 (Windows; U; Windows NT 5.1; zh-CN; rv:1.9) Gecko/20080705 Firefox/3.0 Kapiko/3.0","Mozilla/5.0 (X11; Linux i686; U;) Gecko/20070322 Kazehakase/0.4.5","Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.9.0.8) Gecko Fedora/1.9.0.8-1.fc10 Kazehakase/0.5.6","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/535.11 (KHTML, like Gecko) Chrome/17.0.963.56 Safari/535.11","Mozilla/5.0 (Macintosh; Intel Mac OS X 10_7_3) AppleWebKit/535.20 (KHTML, like Gecko) Chrome/19.0.1036.7 Safari/535.20","Opera/9.80 (Macintosh; Intel Mac OS X 10.6.8; U; fr) Presto/2.9.168 Version/11.52", ]PROXIES = [{'ip_port': '111.11.228.75:80', 'user_pass': ''},{'ip_port': '120.198.243.22:80', 'user_pass': ''},{'ip_port': '111.8.60.9:8123', 'user_pass': ''},{'ip_port': '101.71.27.120:80', 'user_pass': ''},{'ip_port': '122.96.59.104:80', 'user_pass': ''},{'ip_port': '122.224.249.122:8088', 'user_pass': ''}, ]

    代理 IP可以網上搜索一下,上面的代理IP獲取自:http://www.xici.net.co/

    禁用 cookies:

    COOKIES_ENABLED = False

    設置下載延遲:

    DOWNLOAD_DELAY=3

    設置 DOWNLOADER_MIDDLEWARES?

    DOWNLOADER_MIDDLEWARES = {'cnblogs.middlewares.RandomUserAgent': 1,'scrapy.downloadermiddlewares.httpproxy.HttpProxyMiddleware': 110,'cnblogs.middlewares.ProxyMiddleware': 100, }

    保存 settings.py

    3、測試

    [root@bogon cnblogs]# scrapy crawl CnblogsSpider

    本文的 user agent 和 proxy 列表都是采用 settings.py 的方式進行設置的,實際生產中 user agent 和 proxy 有可能會經常更新,每次更改配置文件顯得很笨拙也不便于管理。因而,可以根據需要保存在 mysql 數據庫

    SSL中間人監測關鍵技術 --- SSL會話劫持

    數據流重定向技術是SSL中間人監測的基礎,該技術的使用使得被監測主機與SSL服務器的通信流量都會經過監測主機。對于一般的中間人監測來說,再加上數據轉發機制就已經足夠。但對于SSL中間人監測來說,僅僅通過數據流重定向得到的都是經過加密后的數據,無法直接用來進行HTTP協議解析。故此必需使用SSL會話劫持技術,才能得到被監測主機與SSL服務器之間通信數據的明文。

    自SSL問世以來,在其應用范圍越來越廣泛同時,多種針對SSL協議本身的缺陷或者其不規范引用的SSL會話劫持方法也隨之出現,下面將詳細分析兩種典型的SSL會話劫持的實現原理和實現條件。

    一、利用偽造的 X.509 證書

    1.1 會話劫持原理

    當 SSL 客戶端與 SSL 服務端建立連接時,在正常的連接握手階段,客戶端必定會要求服務端出示其X.509公鑰證書,并根據以下3個要素驗證服務器證書的有效性:

    • a) 該公鑰證書的subject name(主題名)和所訪問的服務器站點的名稱是否一致;
    • b) 該公鑰證書的是否過期;
    • c) 該公鑰證書及其簽發者證書鏈中的證書的數字簽名是否有效(層層驗證,一直驗證到根CA證書為止)。

    當 SSL 客戶端訪問一個基于 HTTPS 的加密 Web 站點時,只要上述三個要素有一個驗證沒有通過,SSL 協議就會發出告警,大多數瀏覽器會彈出一個提示框,提示服務器證書存在的問題,但不會直接斷開SSL連接,而是讓用戶決定是否繼續。下圖展示了IE 瀏覽器彈出的安全警報提示框。

    大多數瀏覽器在驗證到服務器證書存在問題后的處理方式是存在巨大隱患的,因為用戶往往由于缺乏安全意識或者圖方便而選擇接受不安全的證書,這就使得偽造一個和合法證書極為相似的“偽證書”騙取 SSL 客戶端用戶信任的手段成為可能。下圖展示了這種 SSL 會話劫持的主要流程(圖中,C 為 SSL 客戶端,M 為監測主機,S 為 SSL 服務端)

    上圖就是基于偽造證書進行劫持的流程,文字描述如下 :主機M通過數據流重定向技術,使得主機C與主機S之間的通信流量都流向主機M,主機C本欲與主機S建立SSL連接,但發送的連接建立請求被重定向到了主機M; 主機C首先與主機M建立TCP連接,然后向主機M發起SSL連接請求; 主機M收到來自主機C的連接請求后,首先與主機S建立TCP連接,然后向主機S發起SSL連接請求; 主機S響應主機M的請求,由此主機M與主機S之間成功建立SSL連接,主機M同時獲得主機S的X.509公鑰證書Certificate_S; 主機M根據Certificate_S中的關鍵信息(主要是subject name、有效期限等)偽造一個極相似的自簽名證書Certificate_S’,并以此證書響應第②步中,來自主機C的SSL連接請求; 主機C的瀏覽器驗證Certificate_S’的有效性,發現subject name與請求的站點名稱一致,證書還在有效期內,但是并非由信任的機構頒發。于是彈出提示框,讓用戶選擇是否繼續。由于Certificate_S’與Certificate_S從外表上幾乎看不出來差別,大部分用戶會選擇繼續( 這是SSL會話劫持可以成功的關鍵 ),由此主機C與主機M成功建立SSL連接。 這樣以后,主機C發往SSL服務端的數據,主機M可以捕獲并解密查看;主機S返回給SSL客戶端的數據,主機M也可以捕獲并解密查看。至此,主機M實現了完整的SSL中間人監測。 經過以上步驟,主機M成功實現了主機C(SSL客戶端)與主機S(SSL服務端)之間的會話劫持,并可以對明文形式的會話內容進行監測。

    1.2 成功的必要條件 這種類型的 SSL 會話劫持成功的必要條件如下:

    • a) 能夠通過ARP欺騙、DNS欺騙或者瀏覽器數據重定向等欺騙技術,使得SSL客戶端C和服務端S之間的數據都流向中間人監測主機;
    • b) SSL客戶端在接收到偽造的X.509證書后,用戶選擇信任該證書,并繼續SSL連接;
    • c) SSL服務端未要求對SSL客戶端進行認證。

    二、利用 HTTP 與 HTTPS 之間跳轉的驗證漏洞

    2.1 會話劫持原理

    用戶瀏覽網頁時,使用 SSL 協議的方式一般有兩種。一種是在瀏覽器地址欄輸入網址時直接指定協議類型為HTTPS,另一種是通過HTTP響應的302狀態將網頁重定向到HTTPS 鏈接。2009年2月在美國拉斯維加斯舉行的BlackHat黑客大會上,安全研究人員Moxie Marlinspike 演示了通過自己研發的SSLstrip工具劫持SSL會話來截獲注冊數據的方法,為SSL會話劫持提供了新思路。

    SSLstrip 使用了社會工程學的原理:許多人為了圖方便省事,在輸入網址時一般不考慮傳輸協議,習慣上只是簡單輸入主機名,瀏覽器默認在這種情況下會使用 HTTP 協議。例如用戶為了使用Gmail郵箱,直接輸入accounts.google.com,瀏覽器會給谷歌服務器發送一個HTTP 請求,谷歌服務器認為電子郵件屬于應加密的重要事務,使用HTTP不恰當,應改為使用HTTPS,于是它返回一個狀態碼為302的HTTP 響應,給出一個重定向網址https://accounts.google.com/ServiceLogin?passive=1209600&continue=https%3A%2F%2Faccounts.google.com%2FManageAccount&followup=https%3A%2F%2Faccounts.google.com%2FManageAccount,瀏覽器再使用這個重定向網址發出HTTPS?請求。 一個原本應該從頭到尾使用HTTPS加密會話的過程中混入了使用明文傳輸的HTTP會話,一旦HTTP會話被劫持,HTTPS會話就可能受到威脅 。SSLstrip 正是利用這一點,通過劫持HTTP 會話劫持了SSL會話,下圖所示 SSLstrip 原理示意圖。

    下面具體闡述基于SSLstrip的SSL會話劫持流程(闡述中依然以主機C為SSL客戶端,主機M為監測主機,主機S為SSL服務端):主機M通過ARP重定向技術,使得主機C所有與外網的通信流都會從主機M處經過。 主機C向主機S的一個HTTPS頁面發出一個HTTP請求,主機M監聽這個請求并轉發給主機S。 主機S返回一個狀態碼為302的HTTP 響應報文,報文消息頭中Location頭域以及消息實體中都給出了重定向網址,形式分別為,“Location:?https://***.com/…”與“”。 主機M解析來自主機S的響應報文,將其中所有的https替換成http,指定主機M另一個未使用的端口為通信端口(假設為8181端口),并且記錄修改過的url。需要做的替換包括:消息頭中的“Location:?https://***.com/…”替換成“Location:?http://***.com:8181/…”;消息實體中鏈接“< a href=”https://***.com/…”>”替換成“”。 主機C解析經過篡改后的HTTP響應報文,經過重定向與主機M的8181端口通過HTTP方式建立了連接,二者之間通信數據明文傳輸。 主機M冒充客戶端與主機S建立HTTPS會話,二者之間的通信數據通過密文傳輸,但主機M可以自由地解密這些數據。 經過以上步驟,主機M成功實現了主機C(SSL客戶端)與主機S(SSL服務端)之間的會話劫持,并可以對明文形式的會話內容進行監測。

    2.2 成功的必要條件 這種類型的SSL會話劫持成功的必要條件如下:

    • a) 能夠通過ARP欺騙、DNS欺騙或者瀏覽器數據重定向等欺騙技術,使得SSL客戶端和服務端S之間的數據都流向中間人監測主機;
    • b) 客戶端訪問的Web頁面存在http頁面至https頁面的跳轉;
    • c) SSL服務端未要求對SSL客戶端進行認證。

    三、兩種典型 SSL 會話劫持技術的對比小結

    傳統的基于偽造 X.509 證書的 SSL 會話劫持方式,其最大的問題就在于客戶端瀏覽器會彈出警告提示對話框,這個提示是如此醒目,以至于只要用戶有一定的安全意識和網絡知識,劫持成功的概率就會大大降低。隨著網絡知識的慢慢普及,這種技術的生存空間會越來越小。

    基于 HTTP 與 HTTPS 之間跳轉驗證漏洞的 SSL 會話劫持方式,是近幾年新出的一種技術。在此種方式下,客戶端瀏覽器不會有任何不安全的警告或提示,只是原先的HTTPS連接已經被HTTP連接所替換,迷惑性大大增強。一般為了進一步加強欺騙效果,監測主機還可以一個銀色的“安全鎖”圖案顯示在非安全的網址前面。但其缺陷也很明顯,一旦用戶在瀏覽器地址欄的輸入中指定使用HTTPS協議,就會發現網頁根本無法打開。因此只要用戶養成良好的上網習慣,這種方式的會話劫持就會失敗。

    安裝 pycurl

    安裝命令:

    sudo apt-get install libcurl4-openssl-dev pip install pycurl

    雜項

  • scrapy

    了解 scrapy 已經做過的功能,優化等。。。防止重復造輪子,如,去重,編碼檢測,dns緩存,http長連接,gzip等等。

  • JS相關。

    這個是被問的最多的。看具體情況解決??赡M相關js執行、繞過,或直接調瀏覽器去訪問。自己用一個JS引擎+模擬一個瀏覽器環境難度太大了(參見V8的DEMO)。

    調瀏覽器有很多方法。難以細說,關鍵字如下,selenium,phantomjs,casperjs,ghost,webkit,scrapyjs,splash。一些細節如關掉CSS渲染,圖片加載等。只有scrapyjs是完全異步的,相對是速度最快的,scrapyjs將webkit的事件循環和twisted的事件循環合在一起了。其他的方案要么阻塞,要么用多進程。簡單的js需求(對效率要求不高)隨意選,最優方案是scrapyjs+定制webkit(去掉不需要的功能)。調瀏覽器開頁面是比較耗資源的(主要是cpu)

  • 內容解析。

    對于頁面解析最強大的當然是XPATH、css選擇器、正則表達式,這個對于不同網站不同的使用者都不一樣,就不用過多的說明,附兩個比較好的網址:

    正則表達式入門:http://www.cnblogs.com/huxi/archive/2010/07/04/1771073.html

    正則表達式在線測試:http://tool.oschina.net/regex/

    其次就是解析庫了,常用的有兩個lxml和BeautifulSoup,對于這兩個的使用介紹兩個比較好的網站:

    lxml:http://my.oschina.net/jhao104/blog/639448

    BeautifulSoup:http://cuiqingcai.com/1319.html

    對于這兩個庫,都是HTML/XML的處理庫,Beautifulsoup純python實現,效率低,但是功能實用,比如能用通過結果搜索獲得某個HTML節點的源碼;lxmlC語言編碼,高效,支持Xpath

    機器學習不一定好用(效果問題,人工問題-需要訓練)。還有寫些正則去模糊匹配。

    新聞類似的正文提取有readability,boilerplate。

  • 分布式。

    首先考慮按任務(目標)切分,然后讓不同目標的爬蟲在不同機器上跑

    完全的對等分布式(多爬蟲爬一個目標),把任務隊列替換掉爬蟲改改即可。github里面有幾個現有的實現參考。

    分布式需求可能是偽命題。想清楚為何要分布式。硬件夠不夠,像什么拿一個不支持持久化的url隊列的爬蟲說量大需要分布式的,我只能默念,你為何這么吊。

  • 部署,調度

    部署推薦scrapyd。這也是官方推薦的方法。

    大量爬蟲的調度,這個目前(13-10)沒有現成的合適方法,期望是實現爬蟲的某些配置放數據庫,提供web后臺 ,然后按配置周期、定時運行爬蟲,終止,暫停爬蟲等等??梢詫崿F,但要自己寫不少東西。

  • ip 限制問題

    買的起大量ip的可買(買大量同網段爬可能導致整網段被封)。

    找大量免費的開放http代理,篩選可用的,免費開放代理不可靠,寫個調度機制,自動根據成功次數,延遲等選擇合適代理,這個功能難以在scrapy內實現,參考scrapinghub的crawlera,我完成了一個本地版。

    在開發爬蟲過程中經常會遇到IP被封掉的情況,這時就需要用到代理IP;

    在urllib2包中有ProxyHandler類,通過此類可以設置代理訪問網頁,如下代碼片段:

    import urllib2proxy = urllib2.ProxyHandler({'http': '127.0.0.1:8087'})opener = urllib2.build_opener(proxy)urllib2.install_opener(opener)response = urllib2.urlopen('http://www.baidu.com')print response.read()
  • url 去重

    如果有千萬級的URL需要去重,需要仔細看下scrapy的去重機制和bloom filter(布隆過濾器)。bloomfilter有個公式可以算需要多少內存。另bloomfilter + scrapy在github有現有實現可以參考。

  • 存儲。

    mongodb,mongodb不滿足某些功能時考慮hbase,參考http://blog.scrapinghub.com/2013/05/13/mongo-bad-for-scraped-data/

  • 硬件

    硬件扛不住別玩爬蟲。。。曾在I3 4G 1T上跑爬蟲??ㄔ诖疟Pio(量大,磁盤io差,內存低),出現內存占用飆升。很難調試(調試爬蟲看實際跑耗時較長),初步以為是爬蟲有問題內存占用高導致數據庫卡。調試結果確認為,配置低量太大,導致數據庫慢,數據庫慢之后爬蟲任務隊列占滿內存并開始寫磁盤,又循環導致數據庫慢。

  • 爬蟲監控

    scrapyd自帶簡單的監控,不夠的話用scrapy的webservice自己寫

  • 如何防止死循環

    在 Scrapy 的默認配置中,是根據 url 進行去重的。這個對付一般網站是夠的。但是有一些網站的 SEO 做的很變態:為了讓爬蟲多抓,會根據 request,動態的生成一些鏈接,導致爬蟲 在網站上抓取大量的隨機頁面,甚至是死循環。。

    為了解決這個問題,有2個方案:

    (1) 在 setting.py 中,設定爬蟲的嵌套次數上限(全局設定,實際是通過 DepthMiddleware 實現的):

    DEPTH_LIMIT = 20

    (2) 在 parse 中通過讀取 response 來自行判斷( spider級別設定 ) :

    def parse(self, response):if response.meta['depth'] > 100:print 'Loop?'

    學習爬蟲的正確打開方式

    看了大部分回答不禁嘆口氣,主要是因為看到很多大牛在回答像? "如何入門爬蟲"? 這種問題的時候,一如當年學霸講解題目,跳步無數,然后留下一句? "?不就是這樣推嘛 ",讓一眾小白菜鳥一臉懵逼。。作為一個0起步(之前連python都不會),目前總算掌握基礎,開始向上進階的菜鳥,深知其中的不易,所以我會在這個回答里,盡可能全面、細節地分享給大家從0學習爬蟲的各種步驟,如果對你有幫助,請點贊~


    首先!你要對爬蟲有個明確的認識。。。

    在戰略上藐視:

    “所有網站皆可爬”:互聯網的內容都是人寫出來的,而且都是偷懶寫出來的(不會第一頁是a,下一頁是8),所以肯定有規律,這就給人有了爬取的可能,可以說,天下沒有不能爬的網站 “框架不變”:網站不同,但是原理都類似,大部分爬蟲都是從 發送請求——獲得頁面——解析頁面——下載內容——儲存內容 這樣的流程來進行,只是用的工具不同

    在戰術上重視:

    持之以恒,戒驕戒躁:對于初學入門,不可輕易自滿,以為爬了一點內容就什么都會爬了,爬蟲雖然是比較簡單的技術,但是往深學也是沒有止境的(比如搜索引擎等)!只有不斷嘗試,刻苦鉆研才是王道!(為何有種小學作文即視感)

    然后,你需要一個宏偉的目標,來讓你有持續學習的動力(沒有實操項目,真的很難有動力)

    我要爬整個豆瓣!... 我要爬整個草什么榴社區!我要爬知乎各種妹子的聯系方式*&^#%^$#

    接著,你需要捫心自問一下,自己的 python 基本功吼不吼啊? 吼啊!——OK,開始歡快地學習爬蟲吧 !

    不吼?你還需要學習一個!趕緊回去看Python核心編程教程。至少這些功能和語法你要有基本的掌握 : list,dict:用來序列化你爬的東西 切片:用來對爬取的內容進行分割,生成 條件判斷(if等):用來解決爬蟲過程中哪些要哪些不要的問題 循環和迭代(for while ):用來循環,重復爬蟲動作 文件讀寫操作:用來讀取參數、保存爬下來的內容等

    然后,你需要補充一下下面幾個內容,作為你的知識儲備:

    (注:這里并非要求“掌握”,下面講的兩點,只需要先了解,然后通過具體項目來不斷實踐,直到熟練掌握)

    1、網頁的基本知識:

    基本的HTML語言知識(知道href等大學計算機一級內容即可)

    理解網站的發包和收包的概念(POST GET)

    稍微一點點的js知識,用于理解動態網頁(當然如果本身就懂當然更好啦)

    2、一些分析語言,為接下來解析網頁內容做準備

    NO.1 正則表達式:扛把子技術,總得會最基礎的:

    NO.2 XPATH:高效的分析語言,表達清晰簡單,掌握了以后基本可以不用正則

    參考:XPath 教程[http://link.zhihu.com/?target=http%3A//www.w3school.com.cn/xpath/]

    NO.3 Beautifulsoup:

    美麗湯模塊解析網頁神器,一款神器,如果不用一些爬蟲框架(如后文講到的scrapy),配合request,urllib等模塊(后面會詳細講),可以編寫各種小巧精干的爬蟲腳本

    官網文檔:Beautiful Soup 4.2.0 文檔[http://link.zhihu.com/?target=http%3A//beautifulsoup.readthedocs.org/zh_CN/latest/]

    參考案例:

    接著,你需要一些高效的工具來輔助

    (同樣,這里先了解,到具體的項目的時候,再熟悉運用)

    NO.1 F12 開發者工具:

    看源代碼:快速定位元素

    分析xpath:1、此處建議谷歌系瀏覽器,可以在源碼界面直接右鍵看

    NO.2 抓包工具:

    推薦httpfox,火狐瀏覽器下的插件,比谷歌火狐系自帶的F12工具都要好,可以方便查看網站收包發包的信息

    NO.3 XPATH CHECKER (火狐插件):

    非常不錯的 xpath 測試工具,但是有幾個坑,都是個人踩過的,,在此告誡大家:

    • 1、xpath checker 生成的是絕對路徑,遇到一些動態生成的圖標(常見的有列表翻頁按鈕等),飄忽不定的絕對路徑很有可能造成錯誤,所以這里建議在真正分析的時候,只是作為參考
    • 2、記得把如下圖 xpath 框里的“x:”去掉,貌似這個是早期版本xpath的語法,目前已經和一些模塊不兼容(比如scrapy),還是刪去避免報錯

    NO.4 正則表達測試工具:

    在線正則表達式測試(http://link.zhihu.com/?target=http%3A//tool.oschina.net/regex/) ,拿來多練練手,也輔助分析!里面有很多現成的正則表達式可以用,也可以進行參考!

    ok!這些你都基本有一些了解了,現在開始進入抓取時間,上各種模塊吧!python 的火,很大原因就是各種好用的模塊,這些模塊是居家旅行爬網站常備的——

    urllib urllib2 requests

    **不想重復造輪子,有沒有現成的框架? 華麗麗的scrapy(這塊我會重點講,我的最愛)**

    遇到動態頁面怎么辦?

    selenium,會了這個配合 scrapy 無往不利,是居家旅行爬網站又一神器,

    爬來的東西怎么用?

    pandas(基于 numpy 的數據分析模塊,相信我,如果你不是專門搞 TB 級數據的,這個就夠了)

    然后是數據庫,這里我認為開始并不需要非常深入,在需要的時候再學習即可

    mysql mongodb sqllite

    遇到反爬蟲策略驗證碼之類咋整?

    PIL opencv pybrain

    進階技術

    多線程、分布式

    Python 網頁爬蟲 & 文本處理 & 科學計算 & 機器學習 & 數據挖掘兵器譜

    曾經因為NLTK的緣故開始學習Python,之后漸漸成為我工作中的第一輔助腳本語言,雖然開發語言是C/C++,但平時的很多文本數據處理任務都交給了Python。離開騰訊創業后,第一個作品課程圖譜也是選擇了Python系的Flask框架,漸漸的將自己的絕大部分工作交給了Python。這些年來,接觸和使用了很多Python工具包,特別是在文本處理,科學計算,機器學習和數據挖掘領域,有很多很多優秀的Python工具包可供使用,所以作為Pythoner,也是相當幸福的。其實如果仔細留意微博,你會發現很多這方面的分享,自己也Google了一下,發現也有同學總結了“Python機器學習庫”,不過總感覺缺少點什么。最近流行一個詞,全棧工程師(full stack engineer),作為一個苦逼的創業者,天然的要把自己打造成一個full stack engineer,而這個過程中,這些Python工具包給自己提供了足夠的火力,所以想起了這個系列。當然,這也僅僅是拋磚引玉,希望大家能提供更多的線索,來匯總整理一套Python網頁爬蟲,文本處理,科學計算,機器學習和數據挖掘的兵器譜。

    一、Python網頁爬蟲工具集

    一個真實的項目,一定是從獲取數據開始的。無論文本處理,機器學習和數據挖掘,都需要數據,除了通過一些渠道購買或者下載的專業數據外,常常需要大家自己動手爬數據,這個時候,爬蟲就顯得格外重要了,幸好,Python提供了一批很不錯的網頁爬蟲工具框架,既能爬取數據,也能獲取和清洗數據,我們也就從這里開始了:

    1.?Scrapy

    Scrapy, a fast high-level screen scraping and web crawling framework for Python.

    鼎鼎大名的Scrapy,相信不少同學都有耳聞,課程圖譜中的很多課程都是依靠Scrapy抓去的,這方面的介紹文章有很多,推薦大牛pluskid早年的一篇文章:《Scrapy 輕松定制網絡爬蟲》,歷久彌新。

    官方主頁:http://scrapy.org/
    Github代碼頁:?https://github.com/scrapy/scrapy

    2.?Beautiful Soup

    You didn’t write that awful page. You’re just trying to get some data out of it. Beautiful Soup is here to help. Since 2004, it’s been saving programmers hours or days of work on quick-turnaround screen scraping projects.

    讀書的時候通過《集體智慧編程》這本書知道Beautiful Soup的,后來也偶爾會用用,非常棒的一套工具??陀^的說,Beautifu Soup不完全是一套爬蟲工具,需要配合urllib使用,而是一套HTML/XML數據分析,清洗和獲取工具。

    官方主頁:http://www.crummy.com/software/BeautifulSoup/

    3.?Python-Goose

    Html Content / Article Extractor, web scrapping lib in Python

    Goose最早是用Java寫得,后來用Scala重寫,是一個Scala項目。Python-Goose用Python重寫,依賴了Beautiful Soup。前段時間用過,感覺很不錯,給定一個文章的URL, 獲取文章的標題和內容很方便。

    Github主頁:https://github.com/grangier/python-goose

    二、Python文本處理工具集

    從網頁上獲取文本數據之后,依據任務的不同,就需要進行基本的文本處理了,譬如對于英文來說,需要基本的tokenize,對于中文,則需要常見的中文分詞,進一步的話,無論英文中文,還可以詞性標注,句法分析,關鍵詞提取,文本分類,情感分析等等。這個方面,特別是面向英文領域,有很多優秀的工具包,我們一一道來。

    1.?NLTK?— Natural Language Toolkit

    NLTK is a leading platform for building Python programs to work with human language data. It provides easy-to-use interfaces to over 50 corpora and lexical resources such as WordNet, along with a suite of text processing libraries for classification, tokenization, stemming, tagging, parsing, and semantic reasoning, and an active discussion forum.

    搞自然語言處理的同學應該沒有人不知道NLTK吧,這里也就不多說了。不過推薦兩本書籍給剛剛接觸NLTK或者需要詳細了解NLTK的同學: 一個是官方的《Natural Language Processing with Python》,以介紹NLTK里的功能用法為主,同時附帶一些Python知識,同時國內陳濤同學友情翻譯了一個中文版,這里可以看到:推薦《用Python進行自然語言處理》中文翻譯-NLTK配套書;另外一本是《Python Text Processing with NLTK 2.0 Cookbook》,這本書要深入一些,會涉及到NLTK的代碼結構,同時會介紹如何定制自己的語料和模型等,相當不錯。

    官方主頁:http://www.nltk.org/
    Github代碼頁:https://github.com/nltk/nltk

    2.?Pattern

    Pattern is a web mining module for the Python programming language.

    It has tools for data mining (Google, Twitter and Wikipedia API, a web crawler, a HTML DOM parser), natural language processing (part-of-speech taggers, n-gram search, sentiment analysis, WordNet), machine learning (vector space model, clustering, SVM), network analysis and canvas visualization.

    Pattern由比利時安特衛普大學CLiPS實驗室出品,客觀的說,Pattern不僅僅是一套文本處理工具,它更是一套web數據挖掘工具,囊括了數據抓取模塊(包括Google, Twitter, 維基百科的API,以及爬蟲和HTML分析器),文本處理模塊(詞性標注,情感分析等),機器學習模塊(VSM, 聚類,SVM)以及可視化模塊等,可以說,Pattern的這一整套邏輯也是這篇文章的組織邏輯,不過這里我們暫且把Pattern放到文本處理部分。我個人主要使用的是它的英文處理模塊Pattern.en, 有很多很不錯的文本處理功能,包括基礎的tokenize, 詞性標注,句子切分,語法檢查,拼寫糾錯,情感分析,句法分析等,相當不錯。

    官方主頁:http://www.clips.ua.ac.be/pattern

    3.?TextBlob: Simplified Text Processing

    TextBlob is a Python (2 and 3) library for processing textual data. It provides a simple API for diving into common natural language processing (NLP) tasks such as part-of-speech tagging, noun phrase extraction, sentiment analysis, classification, translation, and more.

    TextBlob是一個很有意思的Python文本處理工具包,它其實是基于上面兩個Python工具包NLKT和Pattern做了封裝(TextBlob stands on the giant shoulders of NLTK and pattern, and plays nicely with both),同時提供了很多文本處理功能的接口,包括詞性標注,名詞短語提取,情感分析,文本分類,拼寫檢查等,甚至包括翻譯和語言檢測,不過這個是基于Google的API的,有調用次數限制。TextBlob相對比較年輕,有興趣的同學可以關注。

    官方主頁:http://textblob.readthedocs.org/en/dev/
    Github代碼頁:https://github.com/sloria/textblob

    4.?MBSP?for Python

    MBSP is a text analysis system based on the TiMBL and MBT memory based learning applications developed at CLiPS and ILK. It provides tools for Tokenization and Sentence Splitting, Part of Speech Tagging, Chunking, Lemmatization, Relation Finding and Prepositional Phrase Attachment.

    MBSP與Pattern同源,同出自比利時安特衛普大學CLiPS實驗室,提供了Word Tokenization, 句子切分,詞性標注,Chunking, Lemmatization,句法分析等基本的文本處理功能,感興趣的同學可以關注。

    官方主頁:http://www.clips.ua.ac.be/pages/MBSP

    5.?Gensim: Topic modeling for humans

    Gensim是一個相當專業的主題模型Python工具包,無論是代碼還是文檔,我們曾經用《如何計算兩個文檔的相似度》介紹過Gensim的安裝和使用過程,這里就不多說了。

    官方主頁:http://radimrehurek.com/gensim/index.html
    github代碼頁:https://github.com/piskvorky/gensim

    6.?langid.py: Stand-alone language identification system

    語言檢測是一個很有意思的話題,不過相對比較成熟,這方面的解決方案很多,也有很多不錯的開源工具包,不過對于Python來說,我使用過langid這個工具包,也非常愿意推薦它。langid目前支持97種語言的檢測,提供了很多易用的功能,包括可以啟動一個建議的server,通過json調用其API,可定制訓練自己的語言檢測模型等,可以說是“麻雀雖小,五臟俱全”。

    Github主頁:https://github.com/saffsd/langid.py

    7.?Jieba: 結巴中文分詞

    “結巴”中文分詞:做最好的Python中文分詞組件 “Jieba” (Chinese for “to stutter”) Chinese text segmentation: built to be the best Python Chinese word segmentation module.

    好了,終于可以說一個國內的Python文本處理工具包了:結巴分詞,其功能包括支持三種分詞模式(精確模式、全模式、搜索引擎模式),支持繁體分詞,支持自定義詞典等,是目前一個非常不錯的Python中文分詞解決方案。

    Github主頁:https://github.com/fxsjy/jieba

    8.?xTAS

    xtas, the eXtensible Text Analysis Suite, a distributed text analysis package based on Celery and Elasticsearch.

    感謝微博朋友?@大山坡的春?提供的線索:我們組同事之前發布了xTAS,也是基于python的text mining工具包,歡迎使用,鏈接:http://t.cn/RPbEZOW。看起來很不錯的樣子,回頭試用一下。

    Github代碼頁:https://github.com/NLeSC/xtas

    三、Python 科學計算工具包

    說起科學計算,大家首先想起的是 Matlab,集數值計算,可視化工具及交互于一身,不過可惜是一個商業產品。開源方面除了GNU Octave在嘗試做一個類似Matlab的工具包外,Python的這幾個工具包集合到一起也可以替代Matlab的相應功能:NumPy+SciPy+Matplotlib+iPython。同時,這幾個工具包,特別是NumPy和SciPy,也是很多Python文本處理 & 機器學習 & 數據挖掘工具包的基礎,非常重要。最后再推薦一個系列《用Python做科學計算》,將會涉及到NumPy, SciPy, Matplotlib,可以做參考。

    1.?NumPy

    NumPy is the fundamental package for scientific computing with Python. It contains among other things:
    1)a powerful N-dimensional array object
    2)sophisticated (broadcasting) functions
    3)tools for integrating C/C++ and Fortran code
    4) useful linear algebra, Fourier transform, and random number capabilities

    Besides its obvious scientific uses, NumPy can also be used as an efficient multi-dimensional container of generic data. Arbitrary data-types can be defined. This allows NumPy to seamlessly and speedily integrate with a wide variety of databases.

    NumPy幾乎是一個無法回避的科學計算工具包,最常用的也許是它的N維數組對象,其他還包括一些成熟的函數庫,用于整合C/C++和Fortran代碼的工具包,線性代數、傅里葉變換和隨機數生成函數等。NumPy提供了兩種基本的對象:ndarray(N-dimensional array object)和 ufunc(universal function object)。ndarray是存儲單一數據類型的多維數組,而ufunc則是能夠對數組進行處理的函數。

    官方主頁:http://www.numpy.org/

    2.?SciPy:Scientific Computing Tools for Python

    SciPy refers to several related but distinct entities:

    1)The SciPy Stack, a collection of open source software for scientific computing in Python, and particularly a specified set of core packages.
    2)The community of people who use and develop this stack.
    3)Several conferences dedicated to scientific computing in Python – SciPy, EuroSciPy and SciPy.in.
    4)The SciPy library, one component of the SciPy stack, providing many numerical routines.

    “SciPy是一個開源的Python算法庫和數學工具包,SciPy包含的模塊有最優化、線性代數、積分、插值、特殊函數、快速傅里葉變換、信號處理和圖像處理、常微分方程求解和其他科學與工程中常用的計算。其功能與軟件MATLAB、Scilab和GNU Octave類似。 Numpy和Scipy常常結合著使用,Python大多數機器學習庫都依賴于這兩個模塊?!薄?引用自“Python機器學習庫”

    官方主頁:http://www.scipy.org/

    3.?Matplotlib

    matplotlib is a python 2D plotting library which produces publication quality figures in a variety of hardcopy formats and interactive environments across platforms. matplotlib can be used in python scripts, the python and ipython shell (ala MATLAB?* or Mathematica??), web application servers, and six graphical user interface toolkits.

    matplotlib 是python最著名的繪圖庫,它提供了一整套和matlab相似的命令API,十分適合交互式地進行制圖。而且也可以方便地將它作為繪圖控件,嵌入GUI應用程序中。Matplotlib可以配合ipython shell使用,提供不亞于Matlab的繪圖體驗,總之用過了都說好。

    官方主頁:http://matplotlib.org/

    4.?iPython

    IPython provides a rich architecture for interactive computing with:

    1)Powerful interactive shells (terminal and Qt-based).
    2)A browser-based notebook with support for code, text, mathematical expressions, inline plots and other rich media.
    3)Support for interactive data visualization and use of GUI toolkits.
    4)Flexible, embeddable interpreters to load into your own projects.
    5)Easy to use, high performance tools for parallel computing.

    “iPython 是一個Python 的交互式Shell,比默認的Python Shell 好用得多,功能也更強大。 她支持語法高亮、自動完成、代碼調試、對象自省,支持 Bash Shell 命令,內置了許多很有用的功能和函式等,非常容易使用。 ” 啟動iPython的時候用這個命令“ipython –pylab”,默認開啟了matploblib的繪圖交互,用起來很方便。

    官方主頁:http://ipython.org/

    四、Python 機器學習 & 數據挖掘 工具包

    機器學習和數據挖掘這兩個概念不太好區分,這里就放到一起了。這方面的開源Python工具包有很多,這里先從熟悉的講起,再補充其他來源的資料,也歡迎大家補充。

    1.?scikit-learn: Machine Learning in Python

    scikit-learn (formerly scikits.learn) is an open source machine learning library for the Python programming language. It features various classification, regression and clustering algorithms including support vector machines, logistic regression, naive Bayes, random forests, gradient boosting, k-means and DBSCAN, and is designed to interoperate with the Python numerical and scientific libraries NumPy and SciPy.

    首先推薦大名鼎鼎的scikit-learn,scikit-learn是一個基于NumPy, SciPy, Matplotlib的開源機器學習工具包,主要涵蓋分類,回歸和聚類算法,例如SVM, 邏輯回歸,樸素貝葉斯,隨機森林,k-means等算法,代碼和文檔都非常不錯,在許多Python項目中都有應用。例如在我們熟悉的NLTK中,分類器方面就有專門針對scikit-learn的接口,可以調用scikit-learn的分類算法以及訓練數據來訓練分類器模型。這里推薦一個視頻,也是我早期遇到scikit-learn的時候推薦過的:推薦一個Python機器學習工具包Scikit-learn以及相關視頻–Tutorial: scikit-learn – Machine Learning in Python

    官方主頁:http://scikit-learn.org/

    2.?Pandas: Python Data Analysis Library

    Pandas is a software library written for the Python programming language for data manipulation and analysis. In particular, it offers data structures and operations for manipulating numerical tables and time series.

    第一次接觸Pandas是由于Udacity上的一門數據分析課程“Introduction to Data Science” 的Project需要用Pandas庫,所以學習了一下Pandas。Pandas也是基于NumPy和Matplotlib開發的,主要用于數據分析和數據可視化,它的數據結構DataFrame和R語言里的data.frame很像,特別是對于時間序列數據有自己的一套分析機制,非常不錯。這里推薦一本書《Python for Data Analysis》,作者是Pandas的主力開發,依次介紹了iPython, NumPy, Pandas里的相關功能,數據可視化,數據清洗和加工,時間數據處理等,案例包括金融股票數據挖掘等,相當不錯。

    官方主頁:http://pandas.pydata.org/

    =====================================================================
    分割線,以上工具包基本上都是自己用過的,以下來源于其他同學的線索,特別是《Python機器學習庫》,《23個python的機器學習包》,做了一點增刪修改,歡迎大家補充
    =====================================================================

    3.?mlpy – Machine Learning Python

    mlpy is a Python module for Machine Learning built on top of NumPy/SciPy and the GNU Scientific Libraries.

    mlpy provides a wide range of state-of-the-art machine learning methods for supervised and unsupervised problems and it is aimed at finding a reasonable compromise among modularity, maintainability, reproducibility, usability and efficiency. mlpy is multiplatform, it works with Python 2 and 3 and it is Open Source, distributed under the GNU General Public License version 3.

    官方主頁:http://mlpy.sourceforge.net/

    4.?MDP:The Modular toolkit for Data Processing

    Modular toolkit for Data Processing (MDP) is a Python data processing framework.
    From the user’s perspective, MDP is a collection of supervised and unsupervised learning algorithms and other data processing units that can be combined into data processing sequences and more complex feed-forward network architectures.
    From the scientific developer’s perspective, MDP is a modular framework, which can easily be expanded. The implementation of new algorithms is easy and intuitive. The new implemented units are then automatically integrated with the rest of the library.
    The base of available algorithms is steadily increasing and includes signal processing methods (Principal Component Analysis, Independent Component Analysis, Slow Feature Analysis), manifold learning methods ([Hessian] Locally Linear Embedding), several classifiers, probabilistic methods (Factor Analysis, RBM), data pre-processing methods, and many others.

    “MDP用于數據處理的模塊化工具包,一個Python數據處理框架。 從用戶的觀點,MDP是能夠被整合到數據處理序列和更復雜的前饋網絡結構的一批監督學習和非監督學習算法和其他數據處理單元。計算依照速度和內存需求而高效的執行。從科學開發者的觀點,MDP是一個模塊框架,它能夠被容易地擴展。新算法的實現是容易且直觀的。新實現的單元然后被自動地與程序庫的其余部件進行整合。MDP在神經科學的理論研究背景下被編寫,但是它已經被設計為在使用可訓練數據處理算法的任何情況中都是有用的。其站在用戶一邊的簡單性,各種不同的隨時可用的算法,及應用單元的可重用性,使得它也是一個有用的教學工具?!?/p>

    官方主頁:http://mdp-toolkit.sourceforge.net/

    5.?PyBrain

    PyBrain is a modular Machine Learning Library for Python. Its goal is to offer flexible, easy-to-use yet still powerful algorithms for Machine Learning Tasks and a variety of predefined environments to test and compare your algorithms.

    PyBrain is short for Python-Based Reinforcement Learning, Artificial Intelligence and Neural Network Library. In fact, we came up with the name first and later reverse-engineered this quite descriptive “Backronym”.

    “PyBrain(Python-Based Reinforcement Learning, Artificial Intelligence and Neural Network)是Python的一個機器學習模塊,它的目標是為機器學習任務提供靈活、易應、強大的機器學習算法。(這名字很霸氣)

    PyBrain正如其名,包括神經網絡、強化學習(及二者結合)、無監督學習、進化算法。因為目前的許多問題需要處理連續態和行為空間,必須使用函數逼近(如神經網絡)以應對高維數據。PyBrain以神經網絡為核心,所有的訓練方法都以神經網絡為一個實例。”

    官方主頁:http://www.pybrain.org/

    6.?PyML?– machine learning in Python

    PyML is an interactive object oriented framework for machine learning written in Python. PyML focuses on SVMs and other kernel methods. It is supported on Linux and Mac OS X.

    “PyML是一個Python機器學習工具包,為各分類和回歸方法提供靈活的架構。它主要提供特征選擇、模型選擇、組合分類器、分類評估等功能?!?/p>

    項目主頁:http://pyml.sourceforge.net/

    7.?Milk:Machine learning toolkit in Python.

    Its focus is on supervised classification with several classifiers available:
    SVMs (based on libsvm), k-NN, random forests, decision trees. It also performs
    feature selection. These classifiers can be combined in many ways to form
    different classification systems.

    “Milk是Python的一個機器學習工具箱,其重點是提供監督分類法與幾種有效的分類分析:SVMs(基于libsvm),K-NN,隨機森林經濟和決策樹。它還可以進行特征選擇。這些分類可以在許多方面相結合,形成不同的分類系統。對于無監督學習,它提供K-means和affinity propagation聚類算法。”

    官方主頁:http://luispedro.org/software/milk

    http://luispedro.org/software/milk

    8.?PyMVPA: MultiVariate Pattern Analysis (MVPA) in Python

    PyMVPA is a Python package intended to ease statistical learning analyses of large datasets. It offers an extensible framework with a high-level interface to a broad range of algorithms for classification, regression, feature selection, data import and export. It is designed to integrate well with related software packages, such as scikit-learn, and MDP. While it is not limited to the neuroimaging domain, it is eminently suited for such datasets. PyMVPA is free software and requires nothing but free-software to run.

    “PyMVPA(Multivariate Pattern Analysis in Python)是為大數據集提供統計學習分析的Python工具包,它提供了一個靈活可擴展的框架。它提供的功能有分類、回歸、特征選擇、數據導入導出、可視化等”

    官方主頁:http://www.pymvpa.org/

    9.?Pyrallel?– Parallel Data Analytics in Python

    Experimental project to investigate distributed computation patterns for machine learning and other semi-interactive data analytics tasks.

    “Pyrallel(Parallel Data Analytics in Python)基于分布式計算模式的機器學習和半交互式的試驗項目,可在小型集群上運行”

    Github代碼頁:http://github.com/pydata/pyrallel

    10.?Monte?– gradient based learning in Python

    Monte (python) is a Python framework for building gradient based learning machines, like neural networks, conditional random fields, logistic regression, etc. Monte contains modules (that hold parameters, a cost-function and a gradient-function) and trainers (that can adapt a module’s parameters by minimizing its cost-function on training data).

    Modules are usually composed of other modules, which can in turn contain other modules, etc. Gradients of decomposable systems like these can be computed with back-propagation.

    “Monte (machine learning in pure Python)是一個純Python機器學習庫。它可以迅速構建神經網絡、條件隨機場、邏輯回歸等模型,使用inline-C優化,極易使用和擴展?!?/p>

    官方主頁:http://montepython.sourceforge.net

    11.?Theano

    Theano is a Python library that allows you to define, optimize, and evaluate mathematical expressions involving multi-dimensional arrays efficiently. Theano features:
    1)tight integration with NumPy – Use numpy.ndarray in Theano-compiled functions.
    2)transparent use of a GPU – Perform data-intensive calculations up to 140x faster than with CPU.(float32 only)
    3)efficient symbolic differentiation – Theano does your derivatives for function with one or many inputs.
    4)speed and stability optimizations – Get the right answer for log(1+x) even when x is really tiny.
    5)dynamic C code generation – Evaluate expressions faster.
    6) extensive unit-testing and self-verification – Detect and diagnose many types of mistake.
    Theano has been powering large-scale computationally intensive scientific investigations since 2007. But it is also approachable enough to be used in the classroom (IFT6266 at the University of Montreal).

    “Theano 是一個 Python 庫,用來定義、優化和模擬數學表達式計算,用于高效的解決多維數組的計算問題。Theano的特點:緊密集成Numpy;高效的數據密集型GPU計算;高效的符號微分運算;高速和穩定的優化;動態生成c代碼;廣泛的單元測試和自我驗證。自2007年以來,Theano已被廣泛應用于科學運算。theano使得構建深度學習模型更加容易,可以快速實現多種模型。PS:Theano,一位希臘美女,Croton最有權勢的Milo的女兒,后來成為了畢達哥拉斯的老婆。”

    12.?Pylearn2

    Pylearn2 is a machine learning library. Most of its functionality is built on top of Theano. This means you can write Pylearn2 plugins (new models, algorithms, etc) using mathematical expressions, and theano will optimize and stabilize those expressions for you, and compile them to a backend of your choice (CPU or GPU).

    “Pylearn2建立在theano上,部分依賴scikit-learn上,目前Pylearn2正處于開發中,將可以處理向量、圖像、視頻等數據,提供MLP、RBM、SDA等深度學習模型。”

    總結

    以上是生活随笔為你收集整理的爬虫教程( 6 ) --- 爬虫 进阶、扩展的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

    欧美阿v高清资源不卡在线播放 | 国产极品视觉盛宴 | 国产区女主播在线观看 | 欧美第一黄网免费网站 | 久久久久se色偷偷亚洲精品av | 男女猛烈xx00免费视频试看 | 亚洲国产av精品一区二区蜜芽 | 久久综合给久久狠狠97色 | 夜夜影院未满十八勿进 | 国产精品爱久久久久久久 | 色情久久久av熟女人妻网站 | 无码av岛国片在线播放 | 中文无码精品a∨在线观看不卡 | 国产亚洲视频中文字幕97精品 | 国产人妻久久精品二区三区老狼 | 国产一区二区三区精品视频 | 红桃av一区二区三区在线无码av | 日本免费一区二区三区最新 | 99久久久无码国产aaa精品 | 欧美喷潮久久久xxxxx | 人人妻人人澡人人爽人人精品浪潮 | av小次郎收藏 | 亚洲爆乳大丰满无码专区 | 51国偷自产一区二区三区 | 俺去俺来也在线www色官网 | v一区无码内射国产 | 精品成人av一区二区三区 | 国产午夜亚洲精品不卡下载 | 四虎影视成人永久免费观看视频 | 久久人妻内射无码一区三区 | 乱人伦人妻中文字幕无码 | 亚洲乱亚洲乱妇50p | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 久久精品国产一区二区三区肥胖 | 亚洲人成网站色7799 | 日本熟妇人妻xxxxx人hd | 漂亮人妻洗澡被公强 日日躁 | 亚洲中文无码av永久不收费 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 国产色视频一区二区三区 | 熟妇人妻无乱码中文字幕 | 鲁大师影院在线观看 | 性色欲网站人妻丰满中文久久不卡 | 亚洲精品综合一区二区三区在线 | 少女韩国电视剧在线观看完整 | 中文字幕无线码免费人妻 | 18精品久久久无码午夜福利 | 无码纯肉视频在线观看 | 人妻与老人中文字幕 | 亚洲欧洲无卡二区视頻 | 亲嘴扒胸摸屁股激烈网站 | 狠狠色噜噜狠狠狠狠7777米奇 | 国产亚洲精品久久久久久 | 在线看片无码永久免费视频 | 偷窥村妇洗澡毛毛多 | 特黄特色大片免费播放器图片 | 九九久久精品国产免费看小说 | 熟妇女人妻丰满少妇中文字幕 | 蜜臀aⅴ国产精品久久久国产老师 | 红桃av一区二区三区在线无码av | 久久精品中文字幕大胸 | 波多野结衣乳巨码无在线观看 | √天堂中文官网8在线 | 免费看男女做好爽好硬视频 | 日本xxxx色视频在线观看免费 | 国产精品毛片一区二区 | 欧美阿v高清资源不卡在线播放 | 国产办公室秘书无码精品99 | 国产特级毛片aaaaaaa高清 | 日日摸天天摸爽爽狠狠97 | 人人澡人摸人人添 | 成人av无码一区二区三区 | 日韩精品成人一区二区三区 | 亚洲综合久久一区二区 | 欧美黑人性暴力猛交喷水 | 国产人妻人伦精品1国产丝袜 | 亚洲熟妇色xxxxx欧美老妇y | 亚洲自偷自偷在线制服 | 亚洲国产精品美女久久久久 | 国产后入清纯学生妹 | 亚洲精品成人av在线 | 国产成人精品久久亚洲高清不卡 | 无码人妻出轨黑人中文字幕 | 国精产品一品二品国精品69xx | 波多野结衣高清一区二区三区 | 波多野结衣aⅴ在线 | 欧美日本免费一区二区三区 | 激情综合激情五月俺也去 | 自拍偷自拍亚洲精品被多人伦好爽 | 免费国产成人高清在线观看网站 | 久久精品女人天堂av免费观看 | 色婷婷香蕉在线一区二区 | 少妇无套内谢久久久久 | 亚洲自偷自拍另类第1页 | 国产人成高清在线视频99最全资源 | 精品成在人线av无码免费看 | 欧美大屁股xxxxhd黑色 | 一本久久a久久精品vr综合 | 波多野结衣一区二区三区av免费 | 久久国产精品_国产精品 | 亚洲一区二区三区偷拍女厕 | 亚洲综合无码一区二区三区 | 亚洲国产综合无码一区 | 国产特级毛片aaaaaaa高清 | 黄网在线观看免费网站 | av无码电影一区二区三区 | 久久久久人妻一区精品色欧美 | 无码午夜成人1000部免费视频 | 国产日产欧产精品精品app | 欧美 丝袜 自拍 制服 另类 | 十八禁视频网站在线观看 | 欧美国产日韩久久mv | 亚洲国产精品成人久久蜜臀 | 福利一区二区三区视频在线观看 | 欧美日韩视频无码一区二区三 | 男人和女人高潮免费网站 | 久久婷婷五月综合色国产香蕉 | 亚洲人亚洲人成电影网站色 | 婷婷五月综合缴情在线视频 | 成人一在线视频日韩国产 | a在线亚洲男人的天堂 | 欧美人与物videos另类 | 亚洲一区二区三区国产精华液 | 亚洲国产精品美女久久久久 | 国产精品亚洲а∨无码播放麻豆 | 久久精品女人的天堂av | 亚洲 高清 成人 动漫 | 中文无码精品a∨在线观看不卡 | 国产精品久久久久久无码 | 欧美精品在线观看 | 色窝窝无码一区二区三区色欲 | 18精品久久久无码午夜福利 | 国产三级精品三级男人的天堂 | 少妇性l交大片欧洲热妇乱xxx | 亚洲中文字幕无码中文字在线 | 九九久久精品国产免费看小说 | 国产av无码专区亚洲awww | 狠狠亚洲超碰狼人久久 | 青青青手机频在线观看 | 最近免费中文字幕中文高清百度 | 日日天日日夜日日摸 | 日韩少妇白浆无码系列 | 自拍偷自拍亚洲精品10p | 99视频精品全部免费免费观看 | 东北女人啪啪对白 | 激情国产av做激情国产爱 | 日韩人妻系列无码专区 | 国产精品亚洲lv粉色 | 在线播放免费人成毛片乱码 | 欧美性猛交xxxx富婆 | 强奷人妻日本中文字幕 | 精品人人妻人人澡人人爽人人 | 国产激情无码一区二区app | 小sao货水好多真紧h无码视频 | 中文无码精品a∨在线观看不卡 | 久久精品国产一区二区三区 | 亚洲国产精品毛片av不卡在线 | 国产在线精品一区二区高清不卡 | 国产亚洲视频中文字幕97精品 | 日日摸天天摸爽爽狠狠97 | 狠狠噜狠狠狠狠丁香五月 | 亚洲欧洲中文日韩av乱码 | 国产精华av午夜在线观看 | 久久99久久99精品中文字幕 | 一个人看的www免费视频在线观看 | 国産精品久久久久久久 | 久久精品人妻少妇一区二区三区 | 国产精品久久久久久亚洲毛片 | 精品久久久中文字幕人妻 | 久久 国产 尿 小便 嘘嘘 | 国产99久久精品一区二区 | 麻花豆传媒剧国产免费mv在线 | 天天爽夜夜爽夜夜爽 | 欧美三级不卡在线观看 | 色妞www精品免费视频 | 国产情侣作爱视频免费观看 | 内射老妇bbwx0c0ck | 综合人妻久久一区二区精品 | 99久久精品日本一区二区免费 | 成人无码精品一区二区三区 | 人妻有码中文字幕在线 | 人妻有码中文字幕在线 | 日本大香伊一区二区三区 | 国产绳艺sm调教室论坛 | 亚洲精品国偷拍自产在线麻豆 | 99久久人妻精品免费二区 | 亚洲s色大片在线观看 | 狠狠色噜噜狠狠狠7777奇米 | 丰满肥臀大屁股熟妇激情视频 | 精品国产福利一区二区 | 精品偷自拍另类在线观看 | 国产绳艺sm调教室论坛 | 玩弄少妇高潮ⅹxxxyw | 综合人妻久久一区二区精品 | 日日摸天天摸爽爽狠狠97 | 午夜不卡av免费 一本久久a久久精品vr综合 | 欧美午夜特黄aaaaaa片 | 人妻aⅴ无码一区二区三区 | 国产亚av手机在线观看 | 中文字幕日韩精品一区二区三区 | 青青青爽视频在线观看 | 特级做a爰片毛片免费69 | 青青青爽视频在线观看 | 久久精品国产亚洲精品 | 中文字幕乱码人妻无码久久 | 国产成人精品视频ⅴa片软件竹菊 | 一本色道久久综合亚洲精品不卡 | 人人超人人超碰超国产 | 蜜臀av无码人妻精品 | 日本一本二本三区免费 | 国产午夜无码精品免费看 | 亚洲欧美中文字幕5发布 | 精品久久久久香蕉网 | 国产莉萝无码av在线播放 | 天堂а√在线地址中文在线 | 久久99精品久久久久婷婷 | 一本一道久久综合久久 | 久久久久99精品成人片 | 精品国精品国产自在久国产87 | 一个人看的www免费视频在线观看 | 国产精品久免费的黄网站 | 色婷婷久久一区二区三区麻豆 | 精品一二三区久久aaa片 | 久久国产精品精品国产色婷婷 | 午夜理论片yy44880影院 | 少妇高潮喷潮久久久影院 | 亚洲精品国产品国语在线观看 | 国产农村妇女高潮大叫 | 国精产品一区二区三区 | 国产农村妇女aaaaa视频 撕开奶罩揉吮奶头视频 | 色婷婷欧美在线播放内射 | 国产人妻人伦精品1国产丝袜 | 性生交大片免费看女人按摩摩 | 狠狠噜狠狠狠狠丁香五月 | 国产成人av免费观看 | 国产精品怡红院永久免费 | 国产偷自视频区视频 | 又大又硬又黄的免费视频 | 国产精品久久久一区二区三区 | 亚洲色在线无码国产精品不卡 | 97无码免费人妻超级碰碰夜夜 | 内射爽无广熟女亚洲 | 国产成人无码av片在线观看不卡 | 免费观看黄网站 | 欧美日韩亚洲国产精品 | 亚洲高清偷拍一区二区三区 | 亚洲七七久久桃花影院 | 欧美成人免费全部网站 | 国精产品一品二品国精品69xx | 欧美freesex黑人又粗又大 | 国产一区二区三区影院 | 美女毛片一区二区三区四区 | 牲欲强的熟妇农村老妇女 | 亚洲综合无码一区二区三区 | 无码国产色欲xxxxx视频 | 日韩av无码一区二区三区不卡 | 老熟女重囗味hdxx69 | 四虎影视成人永久免费观看视频 | 中文字幕无码免费久久99 | 免费无码的av片在线观看 | 最近中文2019字幕第二页 | 日韩亚洲欧美中文高清在线 | 丰满护士巨好爽好大乳 | 2020久久超碰国产精品最新 | 成人女人看片免费视频放人 | 丰满人妻精品国产99aⅴ | 无码毛片视频一区二区本码 | 人人妻人人澡人人爽欧美一区 | 大肉大捧一进一出视频出来呀 | 中文字幕无码av波多野吉衣 | 夜精品a片一区二区三区无码白浆 | 欧美人与物videos另类 | 人人妻人人澡人人爽欧美一区 | 少妇无套内谢久久久久 | 国产精品-区区久久久狼 | 亚洲成av人片在线观看无码不卡 | 内射后入在线观看一区 | 久久综合久久自在自线精品自 | 中文精品无码中文字幕无码专区 | 无码av免费一区二区三区试看 | 色综合视频一区二区三区 | 国产精品久久国产精品99 | 亚洲精品国产精品乱码不卡 | 天下第一社区视频www日本 | 国产av无码专区亚洲a∨毛片 | 强辱丰满人妻hd中文字幕 | 黑人粗大猛烈进出高潮视频 | 日韩在线不卡免费视频一区 | 色噜噜亚洲男人的天堂 | 国产精品无码一区二区三区不卡 | 粉嫩少妇内射浓精videos | 亚洲精品一区二区三区在线 | 亚洲一区二区三区 | 捆绑白丝粉色jk震动捧喷白浆 | 国产成人精品一区二区在线小狼 | 久久精品国产99久久6动漫 | 亚洲精品国产a久久久久久 | 国产av一区二区三区最新精品 | 熟妇女人妻丰满少妇中文字幕 | 在线播放免费人成毛片乱码 | 亚洲成在人网站无码天堂 | 亚洲日本va午夜在线电影 | 日产精品高潮呻吟av久久 | 亚洲成熟女人毛毛耸耸多 | 国产亚洲精品久久久久久国模美 | 久久久久99精品国产片 | 久久 国产 尿 小便 嘘嘘 | 男女超爽视频免费播放 | 精品国产一区二区三区四区 | 国产免费观看黄av片 | 最新国产麻豆aⅴ精品无码 | 日本护士毛茸茸高潮 | 日本精品少妇一区二区三区 | 97se亚洲精品一区 | 中文字幕中文有码在线 | 男人的天堂av网站 | 精品日本一区二区三区在线观看 | 午夜成人1000部免费视频 | 狠狠综合久久久久综合网 | 国产综合久久久久鬼色 | 兔费看少妇性l交大片免费 | 99久久无码一区人妻 | 亚洲欧洲日本无在线码 | 无码纯肉视频在线观看 | 中文字幕 人妻熟女 | 亚洲一区二区三区无码久久 | 国产国语老龄妇女a片 | 欧美老熟妇乱xxxxx | 国产亚洲人成在线播放 | 久久99精品久久久久久 | 亚洲精品国产a久久久久久 | 夜夜高潮次次欢爽av女 | 亚洲中文字幕在线无码一区二区 | 又湿又紧又大又爽a视频国产 | 亚洲日韩乱码中文无码蜜桃臀网站 | 青青草原综合久久大伊人精品 | 国产成人精品优优av | 高中生自慰www网站 | 欧美精品一区二区精品久久 | 久久国产自偷自偷免费一区调 | 丁香花在线影院观看在线播放 | 美女黄网站人色视频免费国产 | 成人亚洲精品久久久久软件 | 麻豆国产丝袜白领秘书在线观看 | 中文字幕日韩精品一区二区三区 | 精品乱码久久久久久久 | 国产精品无套呻吟在线 | 丝袜 中出 制服 人妻 美腿 | 兔费看少妇性l交大片免费 | 国产精品国产自线拍免费软件 | 欧美成人免费全部网站 | 色偷偷人人澡人人爽人人模 | 国产人妻大战黑人第1集 | 亚洲自偷自拍另类第1页 | 日韩欧美群交p片內射中文 | 成人免费视频一区二区 | 俄罗斯老熟妇色xxxx | 人人妻人人澡人人爽精品欧美 | 国产内射爽爽大片视频社区在线 | av无码不卡在线观看免费 | 欧美野外疯狂做受xxxx高潮 | 成在人线av无码免观看麻豆 | 领导边摸边吃奶边做爽在线观看 | 丝袜足控一区二区三区 | 精品乱码久久久久久久 | 日本护士毛茸茸高潮 | 亚洲国产精品无码一区二区三区 | 又大又紧又粉嫩18p少妇 | 正在播放东北夫妻内射 | 中文字幕无码视频专区 | 国产后入清纯学生妹 | 国内精品人妻无码久久久影院蜜桃 | 国产乱码精品一品二品 | 久久亚洲中文字幕无码 | 国产人成高清在线视频99最全资源 | 奇米影视7777久久精品人人爽 | 熟妇女人妻丰满少妇中文字幕 | 婷婷五月综合激情中文字幕 | 欧美日韩精品 | 国产xxx69麻豆国语对白 | 东京热无码av男人的天堂 | 亚洲一区二区三区国产精华液 | 18禁止看的免费污网站 | 天天做天天爱天天爽综合网 | 亚洲色在线无码国产精品不卡 | 国产精品久久久久久亚洲影视内衣 | 玩弄人妻少妇500系列视频 | 自拍偷自拍亚洲精品被多人伦好爽 | 无码一区二区三区在线 | 18精品久久久无码午夜福利 | 国产精品99久久精品爆乳 | 无码av岛国片在线播放 | 成人av无码一区二区三区 | 日本护士xxxxhd少妇 | 妺妺窝人体色www在线小说 | 四十如虎的丰满熟妇啪啪 | 久久综合狠狠综合久久综合88 | 亚洲欧美精品aaaaaa片 | 久久国产精品偷任你爽任你 | 欧美一区二区三区 | 在线天堂新版最新版在线8 | 国内精品久久毛片一区二区 | 曰韩少妇内射免费播放 | 亚洲乱亚洲乱妇50p | 成人无码精品一区二区三区 | 国产精品国产自线拍免费软件 | 成人无码影片精品久久久 | 国产人妻久久精品二区三区老狼 | 特级做a爰片毛片免费69 | 国产在线无码精品电影网 | 色婷婷久久一区二区三区麻豆 | 国产精品久久国产三级国 | 九九久久精品国产免费看小说 | 天堂亚洲2017在线观看 | 国产成人精品久久亚洲高清不卡 | 久久精品丝袜高跟鞋 | 国产婷婷色一区二区三区在线 | 国产精品99久久精品爆乳 | 久久精品国产99精品亚洲 | 亚洲天堂2017无码 | 国产综合在线观看 | 午夜熟女插插xx免费视频 | 免费国产黄网站在线观看 | 强奷人妻日本中文字幕 | 亚洲精品国产a久久久久久 | 十八禁真人啪啪免费网站 | 国产精品无码一区二区桃花视频 | 亚洲精品鲁一鲁一区二区三区 | 蜜桃视频插满18在线观看 | 少妇厨房愉情理9仑片视频 | 中文字幕乱码亚洲无线三区 | 色狠狠av一区二区三区 | 麻豆国产97在线 | 欧洲 | 国产偷国产偷精品高清尤物 | 中文字幕久久久久人妻 | 色综合久久久无码网中文 | 久久亚洲日韩精品一区二区三区 | 狠狠色丁香久久婷婷综合五月 | 在线精品国产一区二区三区 | 99久久无码一区人妻 | 成人试看120秒体验区 | 午夜福利电影 | 国产精品igao视频网 | 亚洲精品综合一区二区三区在线 | 国产综合色产在线精品 | 国产精品久久久久久无码 | 人人妻人人澡人人爽精品欧美 | 国产婷婷色一区二区三区在线 | 99久久亚洲精品无码毛片 | 无码午夜成人1000部免费视频 | 波多野结衣aⅴ在线 | 亚洲中文字幕av在天堂 | 久9re热视频这里只有精品 | 18禁止看的免费污网站 | 国产亚洲精品久久久久久久 | 无码播放一区二区三区 | 亚洲狠狠婷婷综合久久 | 76少妇精品导航 | 97精品国产97久久久久久免费 | 水蜜桃色314在线观看 | 久久人人爽人人爽人人片ⅴ | 初尝人妻少妇中文字幕 | 曰本女人与公拘交酡免费视频 | 久久久久免费看成人影片 | 亚洲人成网站在线播放942 | 国产成人无码av一区二区 | 国产亚洲欧美在线专区 | 性色欲网站人妻丰满中文久久不卡 | 亚洲欧美中文字幕5发布 | 性生交大片免费看l | 国产精品久久久久无码av色戒 | 乱人伦人妻中文字幕无码 | 欧美性黑人极品hd | 东京无码熟妇人妻av在线网址 | 免费观看的无遮挡av | 色狠狠av一区二区三区 | 国产一精品一av一免费 | 中文字幕无码免费久久99 | 国产精品第一区揄拍无码 | 日本熟妇大屁股人妻 | 日本一卡2卡3卡四卡精品网站 | 少妇太爽了在线观看 | 亚洲国产欧美日韩精品一区二区三区 | 久久综合给合久久狠狠狠97色 | 亚洲国产欧美日韩精品一区二区三区 | 国产三级久久久精品麻豆三级 | 无码国内精品人妻少妇 | 日韩av无码一区二区三区不卡 | 色婷婷久久一区二区三区麻豆 | 亚洲中文字幕无码一久久区 | 精品 日韩 国产 欧美 视频 | 国产精品久久久久7777 | 小泽玛莉亚一区二区视频在线 | 中文字幕人妻无码一夲道 | 亚洲欧美综合区丁香五月小说 | 亚洲自偷自偷在线制服 | 国产一区二区三区四区五区加勒比 | 夜夜影院未满十八勿进 | 亚洲欧洲日本综合aⅴ在线 | 日本精品人妻无码免费大全 | 久久国语露脸国产精品电影 | 天天摸天天透天天添 | 波多野结衣乳巨码无在线观看 | 人妻少妇精品无码专区动漫 | 六月丁香婷婷色狠狠久久 | 色一情一乱一伦 | 99精品无人区乱码1区2区3区 | 欧美日韩人成综合在线播放 | 丰腴饱满的极品熟妇 | 欧美 日韩 人妻 高清 中文 | 国产精品无码mv在线观看 | 亚洲日本一区二区三区在线 | 欧美人与牲动交xxxx | 国产内射爽爽大片视频社区在线 | 国产色xx群视频射精 | 在线а√天堂中文官网 | 欧美日本免费一区二区三区 | 激情亚洲一区国产精品 | 国产办公室秘书无码精品99 | 国产精品久久久久久久9999 | 国产午夜亚洲精品不卡 | 爽爽影院免费观看 | 扒开双腿疯狂进出爽爽爽视频 | 精品久久久中文字幕人妻 | 牲交欧美兽交欧美 | 欧美性黑人极品hd | 中文字幕无码乱人伦 | 成人女人看片免费视频放人 | 最近中文2019字幕第二页 | ass日本丰满熟妇pics | 中国大陆精品视频xxxx | 久久精品国产日本波多野结衣 | 久久精品一区二区三区四区 | 无码午夜成人1000部免费视频 | 国产免费久久精品国产传媒 | 成人女人看片免费视频放人 | 野外少妇愉情中文字幕 | 成人女人看片免费视频放人 | 99精品视频在线观看免费 | 亚洲国产精品一区二区第一页 | 亚洲精品综合五月久久小说 | 欧美黑人性暴力猛交喷水 | 欧美日韩在线亚洲综合国产人 | 久久久久久久人妻无码中文字幕爆 | 国产精品嫩草久久久久 | 在线a亚洲视频播放在线观看 | 国产精品久久久午夜夜伦鲁鲁 | 欧美日韩在线亚洲综合国产人 | 国产绳艺sm调教室论坛 | 国产精品美女久久久网av | 性生交大片免费看l | 午夜理论片yy44880影院 | 国产精品亚洲专区无码不卡 | 成人性做爰aaa片免费看不忠 | 色五月五月丁香亚洲综合网 | 久久99精品久久久久婷婷 | 乌克兰少妇性做爰 | 亚洲码国产精品高潮在线 | 国产精品va在线播放 | 鲁一鲁av2019在线 | 国产亚洲日韩欧美另类第八页 | 天堂在线观看www | 曰韩少妇内射免费播放 | 亚洲午夜久久久影院 | 久久精品中文字幕大胸 | 欧美老妇交乱视频在线观看 | 国产亲子乱弄免费视频 | 牲欲强的熟妇农村老妇女视频 | 欧美刺激性大交 | 免费观看又污又黄的网站 | 又黄又爽又色的视频 | 亚欧洲精品在线视频免费观看 | 亚洲欧美综合区丁香五月小说 | 欧美丰满少妇xxxx性 | 任你躁在线精品免费 | 久久国语露脸国产精品电影 | 四虎永久在线精品免费网址 | 人妻有码中文字幕在线 | 无码人妻精品一区二区三区不卡 | 国产av一区二区三区最新精品 | а√天堂www在线天堂小说 | 波多野结衣aⅴ在线 | 久久aⅴ免费观看 | 久久精品女人天堂av免费观看 | 午夜精品一区二区三区的区别 | 国产精品手机免费 | 日韩精品一区二区av在线 | 女人被男人躁得好爽免费视频 | 性史性农村dvd毛片 | 久久综合狠狠综合久久综合88 | 九一九色国产 | 国产在热线精品视频 | 激情五月综合色婷婷一区二区 | 国产农村妇女高潮大叫 | 亚洲人成影院在线无码按摩店 | 99久久精品午夜一区二区 | 最新国产乱人伦偷精品免费网站 | 亚洲欧美国产精品久久 | 爽爽影院免费观看 | 性色欲网站人妻丰满中文久久不卡 | 婷婷色婷婷开心五月四房播播 | 熟妇人妻无乱码中文字幕 | 宝宝好涨水快流出来免费视频 | 激情亚洲一区国产精品 | 蜜臀aⅴ国产精品久久久国产老师 | 久久精品99久久香蕉国产色戒 | 精品人人妻人人澡人人爽人人 | 夜先锋av资源网站 | 久久天天躁夜夜躁狠狠 | 亚洲一区二区三区无码久久 | 欧美一区二区三区视频在线观看 | 国产精品igao视频网 | 无码成人精品区在线观看 | 思思久久99热只有频精品66 | 国产两女互慰高潮视频在线观看 | 国产亚洲精品久久久久久国模美 | 日本www一道久久久免费榴莲 | 又大又紧又粉嫩18p少妇 | 少妇人妻偷人精品无码视频 | 国产精品无码成人午夜电影 | 人妻天天爽夜夜爽一区二区 | 久久国产自偷自偷免费一区调 | 亚洲精品国偷拍自产在线麻豆 | 午夜丰满少妇性开放视频 | 狂野欧美性猛xxxx乱大交 | 男人扒开女人内裤强吻桶进去 | 国产婷婷色一区二区三区在线 | 国产香蕉尹人视频在线 | 久久午夜无码鲁丝片 | 性做久久久久久久免费看 | 欧美熟妇另类久久久久久多毛 | 精品国精品国产自在久国产87 | 久久久久av无码免费网 | 国产麻豆精品精东影业av网站 | 国精产品一品二品国精品69xx | 精品国产一区二区三区四区 | 一本久道久久综合婷婷五月 | 久久精品丝袜高跟鞋 | 少妇邻居内射在线 | 丰满少妇熟乱xxxxx视频 | 国产精品亚洲一区二区三区喷水 | 精品无码一区二区三区爱欲 | v一区无码内射国产 | 色五月丁香五月综合五月 | 又色又爽又黄的美女裸体网站 | 在线 国产 欧美 亚洲 天堂 | 内射后入在线观看一区 | 中文字幕无码免费久久9一区9 | 国产成人无码a区在线观看视频app | 亚欧洲精品在线视频免费观看 | 久久99精品国产麻豆 | 综合激情五月综合激情五月激情1 | 国产精品多人p群无码 | 人妻少妇被猛烈进入中文字幕 | 午夜丰满少妇性开放视频 | 美女张开腿让人桶 | 伊人久久婷婷五月综合97色 | 国产9 9在线 | 中文 | 在线播放亚洲第一字幕 | 欧美精品免费观看二区 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲国产欧美国产综合一区 | 纯爱无遮挡h肉动漫在线播放 | 日日噜噜噜噜夜夜爽亚洲精品 | 日日干夜夜干 | 狠狠色丁香久久婷婷综合五月 | 久久www免费人成人片 | 麻花豆传媒剧国产免费mv在线 | 久久久婷婷五月亚洲97号色 | 无码国模国产在线观看 | 婷婷丁香六月激情综合啪 | 伊人久久大香线蕉av一区二区 | 中文久久乱码一区二区 | 国产成人无码av一区二区 | 青青青手机频在线观看 | 精品国产一区av天美传媒 | 午夜免费福利小电影 | 亚洲精品中文字幕久久久久 | 精品一区二区三区波多野结衣 | 在线观看国产午夜福利片 | 国产激情艳情在线看视频 | 国産精品久久久久久久 | 国产精品第一国产精品 | 强奷人妻日本中文字幕 | 动漫av网站免费观看 | 国产suv精品一区二区五 | 国产黑色丝袜在线播放 | 日本熟妇浓毛 | 欧美野外疯狂做受xxxx高潮 | 亚洲欧美中文字幕5发布 | 久久久国产一区二区三区 | а√资源新版在线天堂 | 国产无遮挡又黄又爽免费视频 | 麻豆人妻少妇精品无码专区 | 内射巨臀欧美在线视频 | 网友自拍区视频精品 | 成在人线av无码免费 | 蜜桃av抽搐高潮一区二区 | 初尝人妻少妇中文字幕 | 久久 国产 尿 小便 嘘嘘 | 爽爽影院免费观看 | 国产免费久久精品国产传媒 | 国产网红无码精品视频 | 沈阳熟女露脸对白视频 | 日日噜噜噜噜夜夜爽亚洲精品 | 一本久久a久久精品亚洲 | 国产精品美女久久久 | 香港三级日本三级妇三级 | 激情人妻另类人妻伦 | 欧美变态另类xxxx | 少妇无码一区二区二三区 | 久久久久久久久888 | 天天拍夜夜添久久精品大 | 老司机亚洲精品影院 | 久久国产自偷自偷免费一区调 | 成在人线av无码免费 | 成人无码影片精品久久久 | 亚洲精品一区二区三区婷婷月 | 中文字幕人成乱码熟女app | 国产疯狂伦交大片 | 97久久精品无码一区二区 | 欧美人与禽猛交狂配 | 国产麻豆精品精东影业av网站 | 久久99精品久久久久久动态图 | 鲁鲁鲁爽爽爽在线视频观看 | 日本精品高清一区二区 | 给我免费的视频在线观看 | 久久综合久久自在自线精品自 | 在线欧美精品一区二区三区 | 国产性生大片免费观看性 | 色婷婷香蕉在线一区二区 | 色情久久久av熟女人妻网站 | 奇米影视7777久久精品 | 亚洲精品一区二区三区大桥未久 | 国产一区二区三区精品视频 | 久久99久久99精品中文字幕 | 中文字幕人妻无码一区二区三区 | 精品无码国产一区二区三区av | 在教室伦流澡到高潮hnp视频 | 精品一区二区不卡无码av | 少妇高潮喷潮久久久影院 | 国产女主播喷水视频在线观看 | 久久精品99久久香蕉国产色戒 | 久久精品人人做人人综合 | 日韩av无码中文无码电影 | 国产热a欧美热a在线视频 | 久久 国产 尿 小便 嘘嘘 | 国内综合精品午夜久久资源 | 国产明星裸体无码xxxx视频 | 亚洲日韩一区二区三区 | 成 人 免费观看网站 | 精品偷拍一区二区三区在线看 | 亚洲国产精品毛片av不卡在线 | 成 人 免费观看网站 | 国产成人av免费观看 | 熟女少妇在线视频播放 | 黑人巨大精品欧美黑寡妇 | 中文字幕人成乱码熟女app | 97无码免费人妻超级碰碰夜夜 | 一本久久a久久精品亚洲 | 领导边摸边吃奶边做爽在线观看 | 久精品国产欧美亚洲色aⅴ大片 | 三级4级全黄60分钟 | 国产午夜手机精彩视频 | 成人精品天堂一区二区三区 | 国产人妻精品一区二区三区不卡 | 永久免费观看国产裸体美女 | 麻豆av传媒蜜桃天美传媒 | 亚洲国产精品成人久久蜜臀 | 国产精品久久久久9999小说 | 亚洲国产成人av在线观看 | 国产精品-区区久久久狼 | 正在播放老肥熟妇露脸 | 一区二区三区高清视频一 | 亚洲第一网站男人都懂 | 红桃av一区二区三区在线无码av | 日韩欧美中文字幕公布 | 免费中文字幕日韩欧美 | 少妇性l交大片 | 国产真实乱对白精彩久久 | 激情内射亚州一区二区三区爱妻 | 精品欧洲av无码一区二区三区 | 久久久久久a亚洲欧洲av冫 | 亚洲一区二区三区偷拍女厕 | 国产精品亚洲专区无码不卡 | 亚洲欧洲日本综合aⅴ在线 | 成人精品视频一区二区三区尤物 | 亚洲最大成人网站 | 男女爱爱好爽视频免费看 | 性开放的女人aaa片 | 国产精品美女久久久 | 欧美日本免费一区二区三区 | 天干天干啦夜天干天2017 | 人妻无码αv中文字幕久久琪琪布 | 亚洲色大成网站www国产 | 中文字幕乱妇无码av在线 | 在线亚洲高清揄拍自拍一品区 | 国产尤物精品视频 | 午夜福利一区二区三区在线观看 | 无遮挡国产高潮视频免费观看 | 中文字幕av无码一区二区三区电影 | 熟妇人妻激情偷爽文 | 国产成人av免费观看 | 精品亚洲韩国一区二区三区 | 高清无码午夜福利视频 | 国产精品内射视频免费 | 综合人妻久久一区二区精品 | 在线精品亚洲一区二区 | 少妇无码吹潮 | 国产精品毛多多水多 | 久久久av男人的天堂 | 欧美一区二区三区视频在线观看 | 色综合视频一区二区三区 | 亚洲人成无码网www | 色偷偷人人澡人人爽人人模 | 无码国产激情在线观看 | 欧美自拍另类欧美综合图片区 | 国产精品久久国产三级国 | 97久久国产亚洲精品超碰热 | 亚洲高清偷拍一区二区三区 | 欧美精品免费观看二区 | 亚洲成色在线综合网站 | 欧美丰满熟妇xxxx性ppx人交 | 国产麻豆精品一区二区三区v视界 | 色偷偷人人澡人人爽人人模 | 婷婷综合久久中文字幕蜜桃三电影 | 99麻豆久久久国产精品免费 | 无码帝国www无码专区色综合 | 日本肉体xxxx裸交 | 国产内射爽爽大片视频社区在线 | 男女性色大片免费网站 | 欧美老人巨大xxxx做受 | 精品久久久久香蕉网 | 亚洲精品午夜无码电影网 | 自拍偷自拍亚洲精品被多人伦好爽 | 亚洲色成人中文字幕网站 | 欧美人与物videos另类 | 国产精品手机免费 | 亚洲伊人久久精品影院 | 日本xxxx色视频在线观看免费 | 国产精品第一国产精品 | 成人毛片一区二区 | 97久久国产亚洲精品超碰热 | 国产美女极度色诱视频www | 国产欧美亚洲精品a | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 国产亚洲日韩欧美另类第八页 | 一二三四社区在线中文视频 | 欧美日韩综合一区二区三区 | 国产真人无遮挡作爱免费视频 | 成年美女黄网站色大免费视频 | 国产9 9在线 | 中文 | 高潮毛片无遮挡高清免费 | 久久 国产 尿 小便 嘘嘘 | 国产亚洲欧美在线专区 | www国产亚洲精品久久网站 | 一本色道久久综合亚洲精品不卡 | 无码人妻黑人中文字幕 | 男女猛烈xx00免费视频试看 | 小sao货水好多真紧h无码视频 | 亚洲人成网站在线播放942 | 亚洲经典千人经典日产 | 无码毛片视频一区二区本码 | 成人精品天堂一区二区三区 | 无码人妻精品一区二区三区不卡 | 夜夜夜高潮夜夜爽夜夜爰爰 | 亚洲日韩乱码中文无码蜜桃臀网站 | 亚洲高清偷拍一区二区三区 | 帮老师解开蕾丝奶罩吸乳网站 | 99久久精品日本一区二区免费 | 日本肉体xxxx裸交 | 国产97在线 | 亚洲 | 亚洲色大成网站www | 熟妇女人妻丰满少妇中文字幕 | 乱人伦人妻中文字幕无码久久网 | 偷窥村妇洗澡毛毛多 | 1000部啪啪未满十八勿入下载 | 波多野结衣aⅴ在线 | 国产精品亚洲综合色区韩国 | 亚洲日本va中文字幕 | 性欧美疯狂xxxxbbbb | 99久久精品日本一区二区免费 | 国产高清不卡无码视频 | 国产精品内射视频免费 | 国产成人无码区免费内射一片色欲 | 亚洲成熟女人毛毛耸耸多 | 国产人妻精品一区二区三区不卡 | 影音先锋中文字幕无码 | 国产高潮视频在线观看 | 久9re热视频这里只有精品 | 日韩精品a片一区二区三区妖精 | 又大又硬又爽免费视频 | 激情内射日本一区二区三区 | 久久亚洲中文字幕无码 | 亚洲色欲久久久综合网东京热 | 鲁一鲁av2019在线 | 成熟人妻av无码专区 | 人人妻人人澡人人爽欧美精品 | 永久免费观看美女裸体的网站 | 黑人巨大精品欧美一区二区 | 少妇无码av无码专区在线观看 | 国产人成高清在线视频99最全资源 | 国产成人一区二区三区别 | 天天躁夜夜躁狠狠是什么心态 | 亚洲娇小与黑人巨大交 | 香港三级日本三级妇三级 | 永久免费观看国产裸体美女 | 欧美性生交活xxxxxdddd | 国产精品无码mv在线观看 | 国产精品久久久久无码av色戒 | 丰满人妻被黑人猛烈进入 | 精品久久久久久亚洲精品 | 亚洲欧美国产精品专区久久 | 精品国偷自产在线 | 在线观看国产一区二区三区 | 在线观看国产午夜福利片 | 荫蒂添的好舒服视频囗交 | 久久综合九色综合欧美狠狠 | 国产莉萝无码av在线播放 | 久久精品国产亚洲精品 | 好爽又高潮了毛片免费下载 | 夜先锋av资源网站 | 日本熟妇乱子伦xxxx | 日本在线高清不卡免费播放 | 99久久精品日本一区二区免费 | 亚洲中文字幕无码一久久区 | 中文久久乱码一区二区 | 国产美女精品一区二区三区 | 天天爽夜夜爽夜夜爽 | 天天摸天天碰天天添 | 国产乱码精品一品二品 | 日日摸天天摸爽爽狠狠97 | 红桃av一区二区三区在线无码av | 成人欧美一区二区三区黑人 | 骚片av蜜桃精品一区 | 天堂在线观看www | 久久成人a毛片免费观看网站 | 久热国产vs视频在线观看 | 人妻人人添人妻人人爱 | 日本在线高清不卡免费播放 | 久久zyz资源站无码中文动漫 | 国产卡一卡二卡三 | 少妇性荡欲午夜性开放视频剧场 | 午夜无码人妻av大片色欲 | 一本大道久久东京热无码av | 人妻少妇被猛烈进入中文字幕 | 又大又紧又粉嫩18p少妇 | 俺去俺来也www色官网 | 天堂无码人妻精品一区二区三区 | 97色伦图片97综合影院 | 亚洲精品中文字幕 | 三上悠亚人妻中文字幕在线 | 亚洲人成人无码网www国产 | 麻豆av传媒蜜桃天美传媒 | 亚洲欧洲日本无在线码 | 在线欧美精品一区二区三区 | 久久久久久九九精品久 | 久久久久久a亚洲欧洲av冫 | 亚洲成av人综合在线观看 | 久久久精品成人免费观看 | 无码午夜成人1000部免费视频 | 亚洲人成影院在线观看 | 狠狠cao日日穞夜夜穞av | 欧美人与物videos另类 | 伊人久久大香线蕉av一区二区 | 麻豆国产丝袜白领秘书在线观看 | 亚拍精品一区二区三区探花 | 国产精品久久久久久亚洲影视内衣 | 女人色极品影院 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲毛片av日韩av无码 | 亚洲经典千人经典日产 | 亚洲乱码日产精品bd | 国产精品久久久久久亚洲影视内衣 | 国产一精品一av一免费 | 日韩欧美中文字幕在线三区 | 国产av无码专区亚洲awww | 少妇一晚三次一区二区三区 | 欧美人与物videos另类 | 帮老师解开蕾丝奶罩吸乳网站 | 中文亚洲成a人片在线观看 | 人妻少妇精品视频专区 | 四虎影视成人永久免费观看视频 | 国产精品二区一区二区aⅴ污介绍 | 狂野欧美性猛交免费视频 | 一个人看的www免费视频在线观看 | 亚洲国产成人av在线观看 | 1000部夫妻午夜免费 | 精品久久综合1区2区3区激情 | 国产精品高潮呻吟av久久 | 亚洲狠狠色丁香婷婷综合 | 久久精品国产99久久6动漫 | 小鲜肉自慰网站xnxx | 国产sm调教视频在线观看 | 老熟妇仑乱视频一区二区 | 日本精品人妻无码免费大全 | 久久久久se色偷偷亚洲精品av | 四虎永久在线精品免费网址 | 男女作爱免费网站 | 亚洲色大成网站www | a国产一区二区免费入口 | 欧美激情一区二区三区成人 | 在线观看国产一区二区三区 | 国产午夜亚洲精品不卡 | 激情亚洲一区国产精品 | 久久国产36精品色熟妇 | 午夜精品久久久久久久 | 男人和女人高潮免费网站 | 亚洲国产综合无码一区 | 成人毛片一区二区 | 日日鲁鲁鲁夜夜爽爽狠狠 | 国产 浪潮av性色四虎 | a国产一区二区免费入口 | 国产精品亚洲一区二区三区喷水 | 亚洲国产一区二区三区在线观看 | 97久久国产亚洲精品超碰热 | 伊在人天堂亚洲香蕉精品区 | 无码午夜成人1000部免费视频 | 无码人妻丰满熟妇区五十路百度 | 人人妻人人藻人人爽欧美一区 | 狠狠cao日日穞夜夜穞av | 国语精品一区二区三区 | 国产精品香蕉在线观看 | 波多野结衣aⅴ在线 | 亚洲欧洲日本综合aⅴ在线 | 激情五月综合色婷婷一区二区 | 夜夜夜高潮夜夜爽夜夜爰爰 | 欧美黑人性暴力猛交喷水 | 久久天天躁夜夜躁狠狠 | 欧洲精品码一区二区三区免费看 | 中文字幕乱码亚洲无线三区 | 精品偷拍一区二区三区在线看 | 天堂在线观看www | 国产精品久久国产精品99 | 免费无码的av片在线观看 | 成 人 免费观看网站 | 国产av一区二区精品久久凹凸 | 欧美亚洲日韩国产人成在线播放 | yw尤物av无码国产在线观看 | 国产精品爱久久久久久久 | 亚洲大尺度无码无码专区 | 一二三四社区在线中文视频 | 亚洲成a人片在线观看无码3d | 东京热一精品无码av | 色综合久久久久综合一本到桃花网 | 一本久久a久久精品vr综合 | 麻豆成人精品国产免费 | 亚洲の无码国产の无码步美 | 人人妻人人藻人人爽欧美一区 | 久久亚洲a片com人成 | 中文字幕人成乱码熟女app | 精品国产国产综合精品 | 亚洲精品综合一区二区三区在线 | 久久伊人色av天堂九九小黄鸭 | 黑人大群体交免费视频 | 欧美freesex黑人又粗又大 | 成 人影片 免费观看 | 无遮挡国产高潮视频免费观看 | 国产亚洲精品久久久闺蜜 | 国产日产欧产精品精品app | 中文字幕无码热在线视频 | 两性色午夜免费视频 | 午夜理论片yy44880影院 | 一个人看的www免费视频在线观看 | 日韩av无码一区二区三区 | 久久久久久av无码免费看大片 | 一区二区三区乱码在线 | 欧洲 | 麻花豆传媒剧国产免费mv在线 | 国产精品沙发午睡系列 | 日韩精品无码免费一区二区三区 | 狠狠亚洲超碰狼人久久 | 国产一区二区三区四区五区加勒比 | 日本一区二区三区免费播放 | 亚洲一区二区三区无码久久 | 又大又硬又黄的免费视频 | 精品乱子伦一区二区三区 | 人人超人人超碰超国产 | 国产综合色产在线精品 | 日本一本二本三区免费 | 99久久亚洲精品无码毛片 | 大肉大捧一进一出好爽视频 | 日本熟妇乱子伦xxxx | 中文字幕无码日韩专区 | 日本一区二区三区免费播放 | 久久www免费人成人片 | 午夜精品久久久内射近拍高清 | 国产精品久久久久影院嫩草 | 久久综合色之久久综合 | 在线观看国产午夜福利片 | 秋霞成人午夜鲁丝一区二区三区 | 日韩欧美群交p片內射中文 | 国语精品一区二区三区 | 亚洲精品综合一区二区三区在线 | 少妇被黑人到高潮喷出白浆 | 国产凸凹视频一区二区 | 成人欧美一区二区三区黑人 | 国产97人人超碰caoprom | 亚洲欧美精品aaaaaa片 | 国产va免费精品观看 | 人妻天天爽夜夜爽一区二区 | 日韩av无码中文无码电影 | 日韩视频 中文字幕 视频一区 | 国产性生大片免费观看性 | 亚洲 欧美 激情 小说 另类 | 精品国产一区二区三区四区 | 激情五月综合色婷婷一区二区 | 天天综合网天天综合色 | 影音先锋中文字幕无码 | 亚洲人成影院在线无码按摩店 | 精品国产一区av天美传媒 | 粉嫩少妇内射浓精videos | 国产精品多人p群无码 | 一本久道久久综合狠狠爱 | 中文字幕久久久久人妻 | 亚洲国产一区二区三区在线观看 | 国产精品无码一区二区桃花视频 | 国产做国产爱免费视频 | 老子影院午夜精品无码 | 亚洲爆乳无码专区 | 九九久久精品国产免费看小说 | 性色欲网站人妻丰满中文久久不卡 | 55夜色66夜色国产精品视频 | 精品aⅴ一区二区三区 | 国产 精品 自在自线 | 55夜色66夜色国产精品视频 | 天天摸天天透天天添 | 中文字幕无码av激情不卡 | 俄罗斯老熟妇色xxxx | 波多野结衣av一区二区全免费观看 | 国产av无码专区亚洲a∨毛片 | www国产亚洲精品久久网站 | 国产精品人人爽人人做我的可爱 | 欧美日韩综合一区二区三区 | 精品久久综合1区2区3区激情 | 全球成人中文在线 | 免费视频欧美无人区码 | 亚洲人成网站在线播放942 | 中文字幕乱码亚洲无线三区 | 亚洲色在线无码国产精品不卡 | 精品熟女少妇av免费观看 | 国产凸凹视频一区二区 | 最新国产乱人伦偷精品免费网站 | 亚洲成熟女人毛毛耸耸多 | 爱做久久久久久 | 久久精品国产日本波多野结衣 | 日日橹狠狠爱欧美视频 | 人人妻在人人 | 久久成人a毛片免费观看网站 | 国产无遮挡又黄又爽又色 | 欧美午夜特黄aaaaaa片 | 无码人妻久久一区二区三区不卡 | 亚洲国产欧美日韩精品一区二区三区 | 国产极品视觉盛宴 | 日日摸天天摸爽爽狠狠97 | 狠狠cao日日穞夜夜穞av | 高潮喷水的毛片 | 无码毛片视频一区二区本码 | 高清无码午夜福利视频 | 亚洲日本一区二区三区在线 | 国产精品久久精品三级 | 一本久久a久久精品亚洲 | 少妇久久久久久人妻无码 | 国内揄拍国内精品人妻 | 无码人妻少妇伦在线电影 | 无码人妻黑人中文字幕 | 国产av无码专区亚洲a∨毛片 | 精品国偷自产在线 | 日韩在线不卡免费视频一区 | 国产高清不卡无码视频 | 成人无码视频在线观看网站 | 97久久国产亚洲精品超碰热 | 亚洲国产av精品一区二区蜜芽 | 波多野结衣av一区二区全免费观看 | aⅴ亚洲 日韩 色 图网站 播放 | 四十如虎的丰满熟妇啪啪 | 国产免费久久精品国产传媒 | 亚洲欧美国产精品专区久久 | 国产极品视觉盛宴 | 国产成人精品无码播放 | 欧美 日韩 亚洲 在线 | 国产乱码精品一品二品 | 最新国产乱人伦偷精品免费网站 | 日本成熟视频免费视频 | 久久亚洲精品中文字幕无男同 | 国产成人无码av在线影院 | 久久综合网欧美色妞网 | 在线播放亚洲第一字幕 | 亚洲一区二区三区含羞草 | 蜜臀av在线观看 在线欧美精品一区二区三区 | 国产精品无码成人午夜电影 | 欧美国产亚洲日韩在线二区 | 97夜夜澡人人双人人人喊 | 亚洲男人av香蕉爽爽爽爽 | 水蜜桃av无码 | 欧美性色19p | 亚洲色成人中文字幕网站 | 日日鲁鲁鲁夜夜爽爽狠狠 | www成人国产高清内射 | 国产精品亚洲а∨无码播放麻豆 | 国产精品第一国产精品 | 99久久久无码国产精品免费 | 日日摸日日碰夜夜爽av | 亚洲中文字幕无码中字 | 午夜精品久久久内射近拍高清 | 精品久久久久久人妻无码中文字幕 | 在线成人www免费观看视频 | 天天躁夜夜躁狠狠是什么心态 | 精品久久久久香蕉网 | 欧洲精品码一区二区三区免费看 | 久久午夜无码鲁丝片秋霞 | 日韩在线不卡免费视频一区 | 中文无码精品a∨在线观看不卡 | 久久人人爽人人人人片 | 午夜精品一区二区三区在线观看 | 国产成人精品视频ⅴa片软件竹菊 | 久久久久久久人妻无码中文字幕爆 | 亚洲欧美日韩国产精品一区二区 | 欧洲熟妇精品视频 | 久久国产精品二国产精品 | 色婷婷久久一区二区三区麻豆 | 久久综合给合久久狠狠狠97色 | 久久精品中文字幕一区 | 99国产精品白浆在线观看免费 | 国产乱人偷精品人妻a片 | 久久久久se色偷偷亚洲精品av | 人妻少妇精品视频专区 | 久久国产精品萌白酱免费 | 午夜精品一区二区三区在线观看 | 欧美黑人乱大交 | 久久国产劲爆∧v内射 | 青草视频在线播放 | 亚洲国产成人a精品不卡在线 | 少妇被粗大的猛进出69影院 | 久久国产精品偷任你爽任你 | 无套内谢的新婚少妇国语播放 | 久久aⅴ免费观看 | 亚洲综合无码一区二区三区 | 狠狠色丁香久久婷婷综合五月 | 日本丰满熟妇videos | 亚洲国产精品无码久久久久高潮 | 窝窝午夜理论片影院 | 又黄又爽又色的视频 | 欧美精品在线观看 | 少妇无码吹潮 | 亚洲精品国产品国语在线观看 | 日产精品高潮呻吟av久久 | 国产精品美女久久久 | 国产无av码在线观看 | 亚洲成av人综合在线观看 | 国产亚洲美女精品久久久2020 | 免费网站看v片在线18禁无码 | 国产精品免费大片 | 国产超碰人人爽人人做人人添 | 亚洲欧美国产精品专区久久 | 午夜精品久久久内射近拍高清 | 清纯唯美经典一区二区 | 好屌草这里只有精品 | 小sao货水好多真紧h无码视频 | 亚洲国产精品久久久天堂 | 伊人色综合久久天天小片 | 国产乱人无码伦av在线a | 久久综合九色综合97网 | 午夜成人1000部免费视频 | 成 人影片 免费观看 | 精品国产av色一区二区深夜久久 | 一区二区传媒有限公司 | 成人欧美一区二区三区黑人免费 | 99视频精品全部免费免费观看 | 中文字幕日产无线码一区 | 国产精品亚洲综合色区韩国 | 国产亚洲精品久久久久久久久动漫 | 无码国产乱人伦偷精品视频 | 高清国产亚洲精品自在久久 | 玩弄人妻少妇500系列视频 | 男女性色大片免费网站 | 精品成人av一区二区三区 | 欧美激情一区二区三区成人 | 中文字幕乱码人妻二区三区 | 亚洲精品国产第一综合99久久 | 少妇性l交大片欧洲热妇乱xxx | 樱花草在线社区www | 俺去俺来也www色官网 | 亚洲色欲色欲欲www在线 | 波多野结衣 黑人 | 无码av中文字幕免费放 | 久久久久99精品国产片 | 波多野结衣乳巨码无在线观看 | 性生交大片免费看女人按摩摩 | 国产艳妇av在线观看果冻传媒 | 午夜无码人妻av大片色欲 | 亚洲伊人久久精品影院 | 男女爱爱好爽视频免费看 | 欧美自拍另类欧美综合图片区 | 欧美猛少妇色xxxxx | 内射老妇bbwx0c0ck | 国产成人综合在线女婷五月99播放 | 色偷偷av老熟女 久久精品人妻少妇一区二区三区 | 99久久久无码国产精品免费 | 欧美日韩一区二区免费视频 | 中文字幕亚洲情99在线 | 色一情一乱一伦 | 精品国产麻豆免费人成网站 | 久久精品国产日本波多野结衣 | 午夜成人1000部免费视频 | 免费人成网站视频在线观看 | 久久精品国产大片免费观看 | 精品国产一区av天美传媒 | 在线a亚洲视频播放在线观看 | 好屌草这里只有精品 | 天堂а√在线地址中文在线 | 欧美日韩一区二区免费视频 | av无码不卡在线观看免费 | 一个人看的www免费视频在线观看 | 蜜桃臀无码内射一区二区三区 | 国产性生交xxxxx无码 | 国产免费观看黄av片 | 日本肉体xxxx裸交 | 欧美老人巨大xxxx做受 | 国产又粗又硬又大爽黄老大爷视 | 色噜噜亚洲男人的天堂 | 欧美怡红院免费全部视频 | 激情五月综合色婷婷一区二区 | 亚洲国精产品一二二线 | 中文字幕无码热在线视频 | 亚洲精品一区二区三区四区五区 | 国产偷国产偷精品高清尤物 | 国产精品久久久久无码av色戒 | 久久亚洲国产成人精品性色 | 无遮挡国产高潮视频免费观看 | 漂亮人妻洗澡被公强 日日躁 | 玩弄人妻少妇500系列视频 | 国产精品高潮呻吟av久久 | 国产香蕉97碰碰久久人人 | 98国产精品综合一区二区三区 | 爆乳一区二区三区无码 | 久久久无码中文字幕久... | 性生交大片免费看l | 大胆欧美熟妇xx | 2020久久超碰国产精品最新 | 国产人成高清在线视频99最全资源 | 日本va欧美va欧美va精品 | 人妻无码久久精品人妻 | 国产精品福利视频导航 | 国产在热线精品视频 | 久热国产vs视频在线观看 | 国产三级久久久精品麻豆三级 | 亚洲一区二区三区 | 国产精品办公室沙发 | 亚洲 高清 成人 动漫 | 最新国产麻豆aⅴ精品无码 | 中文字幕日产无线码一区 | 亚洲午夜无码久久 | 欧美 亚洲 国产 另类 | 在线观看欧美一区二区三区 | 日韩av激情在线观看 | 国产av无码专区亚洲awww | 真人与拘做受免费视频一 | 日韩精品久久久肉伦网站 | 在线播放无码字幕亚洲 | 少妇厨房愉情理9仑片视频 | 两性色午夜视频免费播放 | 久久国语露脸国产精品电影 | 欧美人与禽zoz0性伦交 | 中文字幕色婷婷在线视频 | 亚洲综合无码一区二区三区 | 老熟女乱子伦 | 日本爽爽爽爽爽爽在线观看免 | 国产精品人人妻人人爽 | 性开放的女人aaa片 | 4hu四虎永久在线观看 | 偷窥日本少妇撒尿chinese | 激情亚洲一区国产精品 | 中文亚洲成a人片在线观看 | 全球成人中文在线 | 久久人人97超碰a片精品 | 国产无av码在线观看 | 久久婷婷五月综合色国产香蕉 | 精品人妻人人做人人爽夜夜爽 | 国产麻豆精品精东影业av网站 | 婷婷丁香五月天综合东京热 | 无码午夜成人1000部免费视频 | 精品国偷自产在线 | 亚洲小说春色综合另类 | 国产精品久久精品三级 | 无码午夜成人1000部免费视频 | 中文字幕日产无线码一区 | 男女作爱免费网站 | 97人妻精品一区二区三区 | 亚洲爆乳无码专区 | 色婷婷av一区二区三区之红樱桃 | 亚洲国产综合无码一区 | 蜜桃臀无码内射一区二区三区 | 骚片av蜜桃精品一区 | 久久久久久久人妻无码中文字幕爆 | 亚洲阿v天堂在线 | 日日鲁鲁鲁夜夜爽爽狠狠 | 精品日本一区二区三区在线观看 | 国产无遮挡又黄又爽又色 | 四虎影视成人永久免费观看视频 | 狂野欧美性猛xxxx乱大交 | 亚洲中文字幕成人无码 | 无码毛片视频一区二区本码 | 中文字幕无码日韩欧毛 | 国产精品手机免费 | 国产av无码专区亚洲awww | 伊人久久大香线蕉亚洲 | 亚洲中文字幕无码中字 | 一本久道高清无码视频 | 国产sm调教视频在线观看 | 亚洲一区二区三区无码久久 | 国产精品美女久久久 | 亚洲色欲久久久综合网东京热 | 300部国产真实乱 | 中文亚洲成a人片在线观看 | 亚洲精品一区二区三区四区五区 | 熟妇人妻无乱码中文字幕 | 国产精品久久国产精品99 | 免费视频欧美无人区码 | 亚洲精品美女久久久久久久 | 亚洲区小说区激情区图片区 | 奇米影视888欧美在线观看 | 久久人人爽人人爽人人片ⅴ | 中文字幕av日韩精品一区二区 | 国产精品va在线播放 | 国产乱人伦偷精品视频 | 西西人体www44rt大胆高清 | 无码国产激情在线观看 | 狠狠躁日日躁夜夜躁2020 | 国产真实夫妇视频 | 少妇人妻av毛片在线看 | 正在播放东北夫妻内射 | 国产手机在线αⅴ片无码观看 | 荫蒂添的好舒服视频囗交 | 亚洲国产日韩a在线播放 | 日本熟妇大屁股人妻 | 亚洲日韩精品欧美一区二区 | av无码电影一区二区三区 | 2020最新国产自产精品 | 中文字幕无码热在线视频 | 最近免费中文字幕中文高清百度 | 曰本女人与公拘交酡免费视频 | 国内精品一区二区三区不卡 | 欧美成人免费全部网站 | 亚洲综合伊人久久大杳蕉 | 熟妇人妻无码xxx视频 | 99久久人妻精品免费二区 | 国产午夜福利亚洲第一 | aⅴ亚洲 日韩 色 图网站 播放 | 亚洲精品国产a久久久久久 | 成在人线av无码免费 | 久久久久久av无码免费看大片 | 久久综合香蕉国产蜜臀av | 女高中生第一次破苞av | 欧美成人免费全部网站 | 人人妻人人澡人人爽人人精品 | 日日摸夜夜摸狠狠摸婷婷 | 日韩av无码中文无码电影 | 国产精品高潮呻吟av久久 | 亚洲综合另类小说色区 | 日日鲁鲁鲁夜夜爽爽狠狠 | 久久久久久a亚洲欧洲av冫 | 亚洲综合色区中文字幕 | 成熟妇人a片免费看网站 | 亚洲综合无码一区二区三区 | 亚洲日韩乱码中文无码蜜桃臀网站 | 2019午夜福利不卡片在线 | 久久精品女人的天堂av | 国产成人无码午夜视频在线观看 | 双乳奶水饱满少妇呻吟 | 少妇高潮喷潮久久久影院 | 亚无码乱人伦一区二区 | 天堂久久天堂av色综合 | 欧美成人免费全部网站 | 蜜臀av无码人妻精品 | 国产亚洲欧美日韩亚洲中文色 | 中文字幕 人妻熟女 | 国产亚洲日韩欧美另类第八页 | 亚洲精品一区二区三区在线 | 亚洲成色在线综合网站 | 无遮挡国产高潮视频免费观看 | 久久久久免费看成人影片 | 日韩av无码中文无码电影 | 中文精品久久久久人妻不卡 | 亚洲gv猛男gv无码男同 | 国精品人妻无码一区二区三区蜜柚 | 欧美熟妇另类久久久久久多毛 | 久久久www成人免费毛片 | 国产精品美女久久久久av爽李琼 | 中文字幕色婷婷在线视频 | 国产片av国语在线观看 | 红桃av一区二区三区在线无码av | 亚洲午夜无码久久 | 国产美女精品一区二区三区 | 蜜桃av抽搐高潮一区二区 | 色五月五月丁香亚洲综合网 | 国产乱人伦app精品久久 国产在线无码精品电影网 国产国产精品人在线视 | 国产无套粉嫩白浆在线 | 亚洲乱码国产乱码精品精 | 成人免费视频在线观看 | 伦伦影院午夜理论片 | 扒开双腿疯狂进出爽爽爽视频 | 中文字幕无码日韩专区 | 成人欧美一区二区三区黑人免费 | 久久久久久久女国产乱让韩 | 九月婷婷人人澡人人添人人爽 | 波多野结衣高清一区二区三区 | 亲嘴扒胸摸屁股激烈网站 | 免费网站看v片在线18禁无码 | 男女下面进入的视频免费午夜 | 一本久久a久久精品vr综合 | 久久久精品成人免费观看 | 免费网站看v片在线18禁无码 | 人妻aⅴ无码一区二区三区 | 国产网红无码精品视频 | 天堂一区人妻无码 | 亚洲一区二区三区四区 | 日本一卡2卡3卡四卡精品网站 | 欧美自拍另类欧美综合图片区 | 久久久久免费看成人影片 | 久久久婷婷五月亚洲97号色 | 国产99久久精品一区二区 | 永久免费观看国产裸体美女 | 国产区女主播在线观看 | 高清不卡一区二区三区 | 又湿又紧又大又爽a视频国产 | 国产精品手机免费 | 久久午夜夜伦鲁鲁片无码免费 | 免费看男女做好爽好硬视频 | 国产性猛交╳xxx乱大交 国产精品久久久久久无码 欧洲欧美人成视频在线 | 丝袜足控一区二区三区 | 久久人人爽人人爽人人片ⅴ | 无码国产色欲xxxxx视频 | 亚洲中文字幕在线无码一区二区 | 亚洲爆乳大丰满无码专区 | 国内老熟妇对白xxxxhd | 美女毛片一区二区三区四区 | 久久国语露脸国产精品电影 | 97精品人妻一区二区三区香蕉 | 欧美人与牲动交xxxx | 亚洲国产精品美女久久久久 | 国产麻豆精品精东影业av网站 | 久久久无码中文字幕久... | 欧美丰满老熟妇xxxxx性 | 97人妻精品一区二区三区 | 99久久精品日本一区二区免费 | 无码av中文字幕免费放 | 日韩少妇内射免费播放 | 一本精品99久久精品77 | 国产无遮挡又黄又爽又色 | 国产精品久久久久久亚洲毛片 | 日本一卡2卡3卡4卡无卡免费网站 国产一区二区三区影院 | 伊人久久大香线蕉av一区二区 | 国产激情无码一区二区 | 成在人线av无码免观看麻豆 | 少女韩国电视剧在线观看完整 | 狠狠色色综合网站 | 无码人妻出轨黑人中文字幕 | 黑人巨大精品欧美一区二区 | 人人妻人人藻人人爽欧美一区 | 东京无码熟妇人妻av在线网址 | 天天爽夜夜爽夜夜爽 | 国产三级精品三级男人的天堂 | 亚洲爆乳精品无码一区二区三区 | 久久亚洲国产成人精品性色 | 男人扒开女人内裤强吻桶进去 | 18无码粉嫩小泬无套在线观看 | 久久综合香蕉国产蜜臀av | 亚洲色www成人永久网址 | v一区无码内射国产 | 清纯唯美经典一区二区 | 色 综合 欧美 亚洲 国产 | 伊人久久大香线蕉亚洲 | 粉嫩少妇内射浓精videos | 国产黄在线观看免费观看不卡 | yw尤物av无码国产在线观看 | 纯爱无遮挡h肉动漫在线播放 | 日本护士毛茸茸高潮 | 欧美精品免费观看二区 | 高中生自慰www网站 | 精品欧洲av无码一区二区三区 | 夜夜夜高潮夜夜爽夜夜爰爰 | 国产av无码专区亚洲a∨毛片 | 日本va欧美va欧美va精品 | 国产无av码在线观看 | 亚洲色成人中文字幕网站 | 色欲综合久久中文字幕网 | 无码帝国www无码专区色综合 | 亚洲一区av无码专区在线观看 | 欧美放荡的少妇 | 中文字幕无码热在线视频 | 99久久婷婷国产综合精品青草免费 | 熟妇激情内射com | 久久久久久av无码免费看大片 | 在线精品国产一区二区三区 | 中文字幕日产无线码一区 | 国产午夜手机精彩视频 | 亚洲精品国产a久久久久久 | 国产精品亚洲综合色区韩国 | 奇米影视888欧美在线观看 | 国产手机在线αⅴ片无码观看 | 国产欧美精品一区二区三区 | 99国产精品白浆在线观看免费 | 伊人久久大香线蕉亚洲 | 久久国产精品萌白酱免费 | 99久久精品无码一区二区毛片 | 自拍偷自拍亚洲精品10p | 国产成人一区二区三区在线观看 | 日韩人妻少妇一区二区三区 | 麻花豆传媒剧国产免费mv在线 | 性色av无码免费一区二区三区 | 久久久久久亚洲精品a片成人 | 国产精品香蕉在线观看 | 无码帝国www无码专区色综合 | 暴力强奷在线播放无码 | 国产成人精品优优av | 老太婆性杂交欧美肥老太 | 国产口爆吞精在线视频 | 麻豆精品国产精华精华液好用吗 | 欧美怡红院免费全部视频 | 久久 国产 尿 小便 嘘嘘 | 在教室伦流澡到高潮hnp视频 | 国产精品对白交换视频 | 中文字幕无码热在线视频 | 日本丰满护士爆乳xxxx | 在线成人www免费观看视频 | 伊人久久大香线蕉av一区二区 | 国产成人无码一二三区视频 | 伊人色综合久久天天小片 | 国产极品视觉盛宴 | 99视频精品全部免费免费观看 | 人人妻人人澡人人爽人人精品浪潮 | 国产激情无码一区二区app | 亚洲成av人片在线观看无码不卡 | 国产精品久久久久久亚洲毛片 | 荫蒂添的好舒服视频囗交 | 精品偷自拍另类在线观看 | 欧美 亚洲 国产 另类 | 红桃av一区二区三区在线无码av | 3d动漫精品啪啪一区二区中 | 无码乱肉视频免费大全合集 | 一本久道高清无码视频 | 中文字幕无码av激情不卡 | 激情五月综合色婷婷一区二区 | 色综合久久久无码中文字幕 | 欧美亚洲国产一区二区三区 | 久久精品99久久香蕉国产色戒 | 国产特级毛片aaaaaa高潮流水 | 无码人妻少妇伦在线电影 | 人人妻人人澡人人爽欧美精品 | 蜜桃臀无码内射一区二区三区 | 国产精品毛多多水多 | 亚洲乱码国产乱码精品精 | 99久久99久久免费精品蜜桃 | 久久亚洲国产成人精品性色 | 国产农村乱对白刺激视频 | 人妻少妇精品无码专区动漫 | 日本肉体xxxx裸交 | 水蜜桃色314在线观看 | 亚洲欧美日韩国产精品一区二区 | 精品夜夜澡人妻无码av蜜桃 | 国产欧美熟妇另类久久久 | 天天拍夜夜添久久精品大 | 亚洲中文字幕久久无码 | 亚洲中文字幕无码中文字在线 | 亚洲成av人综合在线观看 | 国产亚洲美女精品久久久2020 | 性欧美videos高清精品 | 国产九九九九九九九a片 | 天天av天天av天天透 | 女人被爽到呻吟gif动态图视看 | 女人被爽到呻吟gif动态图视看 | 亚洲自偷自拍另类第1页 | 性生交大片免费看女人按摩摩 | 精品一区二区不卡无码av | 青青青爽视频在线观看 | 少妇高潮喷潮久久久影院 |