日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 综合教程 >内容正文

综合教程

python爬虫入门 之 移动端数据的爬取

發布時間:2024/1/4 综合教程 25 生活家
生活随笔 收集整理的這篇文章主要介紹了 python爬虫入门 之 移动端数据的爬取 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

第七章 移動端數據的爬取

基于某一款抓包工具 : fiddler ,青花瓷 ,miteproxy

7.1 fiddler 基本配置

7.1.1fiddler簡介和安裝

什么是Fiddler?

Fiddler是位于客戶端和服務器端的HTTP代理,也是目前最常用的http抓包工具之一 。 它能夠記錄客戶端和服務器之間的所有 HTTP請求,可以針對特定的HTTP請求,分析請求數據、設置斷點、調試web應用、修改請求的數據,甚至可以修改服務器返回的數據,功能非常強大,是web調試的利器。

Fiddler安裝

Fiddler下載地址:https://www.telerik.com/fiddler

傻瓜式安裝,一鍵到底。Fiddler軟件界面如圖所示:

7.1.2手機APP抓包設置

Fiddler設置打開Fiddler軟件,打開工具的設置。(Fiddler軟件菜單欄:Tools->Options)在HTTPS中設置如下:

在Connections中設置如下

這里使用默認8888端口,當然也可以自己更改,但是注意不要與已經使用的端口沖突:Allow remote computers to connect:允許別的機器把請求發送到fiddler上來

安全證書下載

在電腦瀏覽器中輸入地址:http://localhost:8888/,點擊FiddlerRoot certificate,下載安全證書:

安全證書安裝

證書是需要在手機上進行安裝的,這樣在電腦Fiddler軟件抓包的時候,手機使用電腦的網卡上網才不會報錯。

Android手機安裝:

把證書放入手機的內置或外置存儲卡上,然后通過手機的"系統安全-》從存儲設備安裝"菜單安裝證書。然后找到拷貝的FiddlerRoot.cer進行安裝即可。安裝好之后,可以在信任的憑證中找到我們已經安裝好的安全證書。

蘋果手機安裝:

保證手機網絡和fiddler所在機器網絡是同一個網段下的在safari中訪問http://fiddle機器ip:fiddler端口,進行證書下載。然后進行安裝證書操作。在手機中的設置-》通用-》關于本機-》證書信任設置-》開啟fiddler證書信任

局域網設置 想要使用Fiddler進行手機抓包,首先要確保手機和電腦的網絡在一個內網中,可以使用讓電腦和手機都連接同一個路由器。當然,也可以讓電腦開放WIFI熱點,手機連入。這里,我使用的方法是,讓手機和電腦同時連入一個路由器中。最后,讓手機使用電腦的代理IP進行上網。 在手機上,點擊連接的WIFI進行網絡修改,添加代理。進行手動設置,ip和端口號都是fiddler機器的ip和fiddler上設置的端口號。

Fiddler手機抓包測試

上述步驟都設置完成之后,用手機瀏覽器打開百度首頁,我們就可以順利抓包了

7.1.3移動端數據的捕獲流程

tools --> options --> connection -->allow remote

http: fiddler所在pc機的ip :8888/ 訪問到一張提供了證書下載功能的界面

fiddler所在機器和手機在同一網段下 :在手機上瀏覽器中訪問 http: fiddler所在pc機的ip :8888 獲取子頁面進行證書的下載和安裝(證書信任的操作)

配置你手機的代理 :將手機的代理配置成 fiddler所對應的pc機的ip和手機自己的端口

就可以讓fiddler捕獲手機發起的http和https的請求

7.2 scrapy ,pyspider

#總結:
?
#爬蟲文件中的屬性和方法
    name :爬蟲文件唯一標識
    start_url:該列表中的url會被自動的進行請求發送
#自動請求發送的過程:
    def start_requests(self):
        for url in self.start_urls:
            yield scrapy.Request(url,callback=self.parse)
?
#數據解析:
    scrapy中封裝的xpath進行數據解析   
    
#scrapy中的xpath 和 etree中的xpath的區別
    scrapy的xpath進行數據解析后返回的列表元素為Selector對象,extract或extract_first這兩個方法將Selector對象中對應的數據取出

View Code

7.2.1Scrapy簡介

什么是框架?如何學習

框架就是一個集成各種功能且具有很強通用性(可以被應用在各種不同的需求中)的一個項目模板

我們只需要學習框架中封裝好的相關功能即可

scrapy 集成的功能

高性能的數據解析操作 ,持久化存儲,高性能的數據下載操作......

環境的安裝(windows)

pip install wheel

下載twisted http://www.lfd.uci.edu/~gohlke/pythonlibs/

進入下載目錄,執行 pip3 install Twisted?17.1.0?cp35?cp35m?win_amd64.whl

pip3 install pywin32

pip3 install scrapy

7.2.2 scrapy的基本使用

創建一個工程 :scrapy startproject firstBlood

項目結構:

project_name/
   scrapy.cfg:            #項目的主配置信息。(真正爬蟲相關的配置信息在settings.py文件中)
   project_name/
       __init__.py  
       items.py            #設置數據存儲模板,用于結構化數據,如:Django的Model
       pipelines.py        #數據持久化處理
       settings.py         #配置文件,如:遞歸的層數、并發數,延遲下載等
       spiders/            #爬蟲目錄,如:創建文件,編寫爬蟲解析規則
           __init__.py

創建爬蟲應用程序:(必須在spider這個目錄下創建一個爬蟲文件)

cd proName

scrapy genspider spiderName http://t.zoukankan.com/www.xx.com

編寫爬蟲文件:在步驟2執行完畢后,會在項目的spiders中生成一個應用名的py爬蟲文件

import scrapy

class FirstSpider(scrapy.Spider):
    #爬蟲文件的名稱:爬蟲文件的唯一標識(在spiders子目錄下是可以創建多個爬蟲文件)
    name = 'first'
    #允許的域名
    # allowed_domains = ['www.baidu.com']
    #起始的url列表:列表中存放的url會被scrapy自動的進行請求發送
    start_urls = ['https://www.baidu.com/','https://www.sogou.com/']
    #用作于數據解析:將start_urls列表中對應的url請求成功后的響應數據進行解析
    def parse(self, response):
        print(response.text) #獲取字符串類型的響應內容
        print(response.body)#獲取字節類型的相應內容

View Code

設置修改settings.py配置文件相關配置

# settings.py 文件中
    #不遵從robots協議
    #進行UA偽裝
    #進行日志等級設定: LOG_LEVEL = False

View Code

setting.py中 ----- 基于終端指令的持久化存儲操作

BOT_NAME = 'firstBlood'

SPIDER_MODULES = ['firstBlood.spiders']
NEWSPIDER_MODULE = 'firstBlood.spiders'


# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'       #進行ua偽裝
# Obey robots.txt rules
ROBOTSTXT_OBEY = False    #不遵從robotstx協議
LOG_LEVEL = 'ERROR'       #輸出錯誤類型的日志

View Code

setting.py ------------- 基于管道的持久化存儲

BOT_NAME = 'qiubaiPro'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'

SPIDER_MODULES = ['qiubaiPro.spiders']
NEWSPIDER_MODULE = 'qiubaiPro.spiders'


ITEM_PIPELINES = {
   'qiubaiPro.pipelines.QiubaiproPipeline': 300, #300表示的是優先級(數值越小優先級越大)
}

View Code

執行爬蟲程序:scripy crawl spiderName

不輸出日志(錯誤信息會在日志中輸出,不要使用)

scripy crawl spiderName --nolog

View Code

7.2.3scrapy框架持久化存儲

#持久化存儲
    #基于終端指令
        特性 : 只能將 parse 方法的返回值存儲到本地的磁盤文件中
        指令 : scripy crawl spiderName -o filepath
    #基于管道
        #實現流程
        1.數據解析
        2.在item類中定義相關屬性
        3.將解析的數據封裝到一個 item 對象中(item文件中對應類的對象)
        4.向管道提交item
        5.在管道文件中的 process_item 方法中接收 item 進行持久化存儲
        6.在配置文件中開啟管道
    
    #管道中需注意細節:
        1.配置文件中開啟的管道是一個字典,字典中的鍵值表示的就是某一個管道
        2.在管道對應的源文件中其實可以定義多個管道類,一種形式的持久化存儲
        3.在process_item方法中的 return item 表示的是提交給下一個即將被執行的管道類
        4.爬蟲文件中yield item 只可以將item傳遞給第一個被執行的(優先級最高的)管道
    
    #將同一份數據持久化存儲到不同平臺中:
        #分析
        1.管道文件中的一個管道內負責數據的一種形式的持久化存儲

setting.py中 ----- 基于終端指令的持久化存儲操作

BOT_NAME = 'firstBlood'

SPIDER_MODULES = ['firstBlood.spiders']
NEWSPIDER_MODULE = 'firstBlood.spiders'


# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'       #進行ua偽裝
# Obey robots.txt rules
ROBOTSTXT_OBEY = False    #不遵從robotstx協議
LOG_LEVEL = 'ERROR'       #輸出錯誤類型的日志

View Code

setting.py ------------- 基于管道的持久化存儲

BOT_NAME = 'qiubaiPro'
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'

SPIDER_MODULES = ['qiubaiPro.spiders']
NEWSPIDER_MODULE = 'qiubaiPro.spiders'


ITEM_PIPELINES = {
   'qiubaiPro.pipelines.QiubaiproPipeline': 300, #300表示的是優先級(數值越小優先級越大)
}

View Code

糗事百科

qiubai.py

import scrapy
from qiubaiPro.items import QiubaiproItem

class QiubaiSpider(scrapy.Spider):
    name = 'qiubai'
    # allowed_domains = ['http://t.zoukankan.com/www.xxx.com']
    start_urls = ['https://www.qiushibaike.com/text/']
    
    #基于終端指令的持久化存儲操作
    # def parse(self, response):
    #     div_list = response.xpath('//*[@id="content-left"]/div')
    #     all_data = []
    #     for div in div_list:
    #         #scrapy中的xpath返回的列表的列表元素一定是Selector對象,我們最終想要的解析的
    #         #數據一定是存儲在該對象中
    #         #extract()將Selector對象中data參數的值取出
    #         # author = div.xpath('./div[1]/a[2]/h2/text()')[0].extract()
    #         author = div.xpath('./div[1]/a[2]/h2/text()').extract_first()
    #         #列表直接調用extract表示的是將extract作用到每一個列表元素中
    #         content = div.xpath('./a[1]/div/span//text()').extract()
    #         content = ''.join(content)
    #         dic = {
    #             'author':author,
    #             'content':content
    #         }
    #         all_data.append(dic)
    #     return all_data
    
   
    #基于管道的持久化存儲
    def parse(self, response):
        div_list = response.xpath('//*[@id="content-left"]/div')
        all_data = []
        for div in div_list:
            #scrapy中的xpath返回的列表的列表元素一定是Selector對象,我們最終想要的解析的
            #數據一定是存儲在該對象中
            #extract()將Selector對象中data參數的值取出
            # author = div.xpath('./div[1]/a[2]/h2/text()')[0].extract()
            author = div.xpath('./div[1]/a[2]/h2/text()').extract_first()
            #列表直接調用extract表示的是將extract作用到每一個列表元素中
            content = div.xpath('./a[1]/div/span//text()').extract()
            content = ''.join(content)

            #將解析的數據存儲到item對象
            item = QiubaiproItem()
            item['author'] = author
            item['content'] = content

            #將item提交給管道
            yield item #item一定是提交給了優先級最高的管道類

View Code

itims.py

import scrapy

class QiubaiproItem(scrapy.Item):
    # define the fields for your item here like:
    author = scrapy.Field() #Field可以將其理解成是一個萬能的數據類型
    content = scrapy.Field()

View Code

pipelines.py 管道文件

import pymysql
from redis import Redis
class QiubaiproPipeline(object):
    fp = None
    def open_spider(self,spider):
        print('開始爬蟲......')
        self.fp = open('qiushibaike.txt','w',encoding='utf-8')

    #使用來接收爬蟲文件提交過來的item,然后將其進行任意形式的持久化存儲
    #參數item:就是接收到的item對象
    #該方法每接收一個item就會調用一次
    def process_item(self, item, spider):
        author = item['author']
        content= item['content']

        self.fp.write(author+':'+content+'
')
        return item #item是返回給了下一個即將被執行的管道類

    def close_spider(self,spider):
        print('結束爬蟲!')
        self.fp.close()

        
#負責將數據存儲到mysql
class MysqlPL(object):
    conn = None
    cursor = None
    def open_spider(self,spider):
        self.conn = pymysql.Connect(host='127.0.0.1',port=3306,user='root',password='123',db='spider',charset='utf8')
        print(self.conn)
    def process_item(self,item,spider):
        author = item['author']
        content = item['content']

        sql = 'insert into qiubai values ("%s","%s")'%(author,content)
        self.cursor = self.conn.cursor()
        try:
            self.cursor.execute(sql)
            self.conn.commit()
        except Exception as e:
            print(e)
            self.conn.rollback()
        return item
    
    def close_spider(self,spider):
        self.cursor.close()
        self.conn.close()

#基于redis的管道存儲
class RedisPL(object):
    conn = None
    def open_spider(self,spider):
        self.conn = Redis(host='127.0.0.1',port=6379)
        print(self.conn)
        
    def process_item(self,item,spider):
        self.conn.lpush('all_data',item)     # name  value
        #注意:如果將字典寫入redis報錯:pip install -U redis==2.10.6

View Code

7.2.4scrapy框架之遞歸解析和post請求

遞歸解析(手動請求發送)

使用場景 :爬取多個頁碼對應的頁面源碼數據

yield scrapy.Request(url,callback)

import scrapy
from qiubaiPro.items import QiubaiproItem

class QiubaiSpider(scrapy.Spider):
    name = 'qiubai'
    # allowed_domains = ['http://t.zoukankan.com/www.xxx.com']
    start_urls = ['https://www.qiushibaike.com/text/']

    #將多個頁碼對應的頁面數據進行爬取和解析的操作
    url = 'https://www.qiushibaike.com/text/page/%d/'#通用的url模板
    pageNum = 1
    #parse第一次調用表示的是用來解析第一頁對應頁面中的段子內容和作者
    def parse(self, response):
        div_list = response.xpath('//*[@id="content-left"]/div')
        all_data = []
        for div in div_list:
            # scrapy中的xpath返回的列表的列表元素一定是Selector對象,我們最終想要的解析的
            # 數據一定是存儲在該對象中
            # extract()將Selector對象中data參數的值取出
            # author = div.xpath('./div[1]/a[2]/h2/text()')[0].extract()
            author = div.xpath('./div[1]/a[2]/h2/text()').extract_first()
            # 列表直接調用extract表示的是將extract作用到每一個列表元素中
            content = div.xpath('./a[1]/div/span//text()').extract()
            content = ''.join(content)

            # 將解析的數據存儲到item對象
            item = QiubaiproItem()
            item['author'] = author
            item['content'] = content

            # 將item提交給管道
            yield item  # item一定是提交給了優先級最高的管道類

        if self.pageNum <= 5:
            self.pageNum += 1
            new_url = format(self.url%self.pageNum)
            #手動請求(get)的發送
            yield scrapy.Request(new_url,callback=self.parse)

View Code

post請求發送

問題:在之前代碼中,我們從來沒有手動的對start_urls列表中存儲的起始url進行過請求的發送,但是起始url的確是進行了請求的發送,那這是如何實現的呢?

解答:其實是因為爬蟲文件中的爬蟲類繼承到了Spider父類中的start_requests(self)這個方法,該方法就可以對start_urls列表中的url發起請求:

  def start_requests(self):
        for u in self.start_urls:
           yield scrapy.Request(url=u,callback=self.parse)

【注意】該方法默認的實現,是對起始的url發起get請求,如果想發起post請求,則需要子類重寫該方法。

方法: 重寫start_requests方法,讓其發起post請求:

def start_requests(self):
        #請求的url
        post_url = 'http://fanyi.baidu.com/sug'
        # post請求參數
        formdata = {
            'kw': 'wolf',
        }
        # 發送post請求
        yield scrapy.FormRequest(url=post_url, formdata=formdata, callback=self.parse)

scrapy五大核心組件

#引擎(Scrapy)
  用來處理整個系統的數據流處理, 觸發事務(框架核心)
#調度器(Scheduler)
  用來接受引擎發過來的請求, 壓入隊列中, 并在引擎再次請求的時候返回. 可以想像成一個URL(抓取網頁的網址或者說是鏈接)的優先隊列, 由它來決定下一個要抓取的網址是什么, 同時去除重復的網址
#下載器(Downloader)
  用于下載網頁內容, 并將網頁內容返回給蜘蛛(Scrapy下載器是建立在twisted這個高效的異步模型上的)
#爬蟲(Spiders)
  爬蟲是主要干活的, 用于從特定的網頁中提取自己需要的信息, 即所謂的實體(Item)。用戶也可以從中提取出鏈接,讓Scrapy繼續抓取下一個頁面
#項目管道(Pipeline)
  負責處理爬蟲從網頁中抽取的實體,主要的功能是持久化實體、驗證實體的有效性、清除不需要的信息。當頁面被爬蟲解析后,將被發送到項目管道,并經過幾個特定的次序處理數據。

工作流程

#步驟
1.spider中的url被封裝成請求對象交給引擎(每一個url對應一個請求對象);
2.引擎拿到請求對象之后, 將其全部交給調度器;
3.調度器拿到所有請求對象后, 通過內部的過濾器過濾掉重復的url, 最后將去重后的所有url對應的請求對象壓入到隊列中, 隨后調度器調度出其中一個請求對象, 并將其交給引擎;
4.引擎將調度器調度出的請求對象交給下載器;
5.下載器拿到該請求對象去互聯網中下載數據;
6.數據下載成功后會被封裝到response中, 隨后response會被交給下載器;
7.下載器將response交給引擎;
8.引擎將response交給spiders;
9.spiders拿到response后調用回調方法進行數據解析, 解析成功后產生item, 隨后spiders將item交給引擎;
10.引擎將item交給管道, 管道拿到item后進行數據的持久化存儲.

7.3基于scrapy進行圖片數據的爬取

示例 :校花網圖片的爬取

鏈接地址 :http://www.521609.com/daxuemeinv/list81.html

項目的創建

scrapy startproject imgPro

cd imgPro

scrapy genspider img http://t.zoukankan.com/www.xxx.com

如何基于scrapy進行圖片的爬取

1.在爬蟲文件中只需要解析出圖片地址,然后將圖片地址提交給管道
2.配置文件中添加  IMAGES_STORE = './imasLib'
1.在管道文件中進行管道類的制定:
    from scrapy.pipelines.images import ImagesPipeline
    將管道的父類修改成 ImagesPipeline
    重寫父類的三個方法

代碼:

img.py

import scrapy
from imgPro.items import ImgproItem

class ImgSpider(scrapy.Spider):
    name = 'img'
    # allowed_domains = ['www.x.com']
    start_urls = ['http://www.521609.com/daxuemeinv/']
    url = 'http://www.521609.com/daxuemeinv/list8%d.html'
    pageNum = 1
    def parse(self, response):
        li_list = response.xpath('//*[@id="content"]/div[2]/div[2]/ul/li')
        for li in li_list:
            img_src = 'http://www.521609.com' + li.xpath('./a[1]/img/@src').extract_first()
            item = ImgproItem()
            item['src'] = img_src

            yield item

        if self.pageNum < 4:
            self.pageNum += 1
            new_url = format(self.url%self.pageNum)
            yield scrapy.Request(new_url,callback=self.parse)

View Code

setting.py

##不遵從robotstx協議
ROBOTSTXT_OBEY = False

#輸出錯誤類型的日志
LOG_LEVEL = 'ERROR'
# LOG_FILE = './log.txt'

#圖片存儲地址
IMAGES_STORE = './imasLib'

ITEM_PIPELINES = {
   'imgPro.pipelines.ImgproPipeline': 300,
}

View Code

pipelines.py

import scrapy
from scrapy.pipelines.images import ImagesPipeline

class ImgproPipeline(ImagesPipeline):

    #對某一個媒體資源進行請求發送
    # item 就是接收到的spider提交的數據
    def get_media_requests(self, item, info):
        yield scrapy.Request(item['src'])

    #指定媒體數據存儲的名稱
    def file_path(self, request, response=None, info=None):
        #返回原始圖片名稱
        name = request.url.split('/')[-1]
        print("正在下載:",name)
        return name

    #將 item 傳遞給下一個即將被執行的管道類
    def item_completed(self, results, item, info):
        return item

View Code

items.py

import scrapy

class ImgproItem(scrapy.Item):
    # define the fields for your item here like:
    src = scrapy.Field()

View Code

如何提升scrapy爬取數據的效率

只需要將如下五個步驟配置在配置文件中即可:

#增加并發
    默認scrapy開啟的并發線程為32個,可以適當進行增加。在settings配置文件中修改CONCURRENT_REQUESTS = 100值為100,并發設置成了為100。
    
#降低日志級別:
    在運行scrapy時,會有大量日志信息的輸出,為了減少CPU的使用率。可以設置log輸出信息為INFO或者ERROR即可。在配置文件中編寫:LOG_LEVEL = ‘INFO’

#禁止cookie:
    如果不是真的需要cookie,則在scrapy爬取數據時可以禁止cookie從而減少CPU的使用率,提升爬取效率。在配置文件中編寫:COOKIES_ENABLED = False

#禁止重試:
    對失敗的HTTP進行重新請求(重試)會減慢爬取速度,因此可以禁止重試。在配置文件中編寫:RETRY_ENABLED = False

#減少下載超時:
    如果對一個非常慢的鏈接進行爬取,減少下載超時可以能讓卡住的鏈接快速被放棄,從而提升效率。在配置文件中進行編寫:DOWNLOAD_TIMEOUT = 10 超時時間為10s

7.4請求傳參

實現深度爬取:爬取多個層級對應的頁面數據

使用場景:爬取的數據沒有在同一張頁面中

在手動請求的時候傳遞item:yield scrapy.Request(url,callback,meta={'item':item})

將meta這個字典傳遞給callback

在callback中接收meta:item = response.meta['item']

代碼:

movie.py

import scrapy
from moviePro.items import MovieproItem

class MovieSpider(scrapy.Spider):
    name = 'movie'
    # allowed_domains = ['http://t.zoukankan.com/www.xxx.com']
    start_urls = ['https://www.4567tv.tv/index.php/vod/show/class/動作/id/5.html']

    url = 'https://www.4567tv.tv/index.php/vod/show/class/動作/id/5/page/%d.html'
    pageNum = 1
    def parse(self, response):
        li_list = response.xpath('/html/body/div[1]/div/div/div/div[2]/ul/li')
        for li in li_list:
            title = li.xpath('./div[1]/a/@title').extract_first()
            detail_url = "https://www.4567tv.tv" + li.xpath('./div[1]/a/@href').extract_first()

            item = MovieproItem()
            item['title'] = title
            # meta參數是一個字典,該參數可以傳遞給callback指定的回調函數,
            yield scrapy.Request(detail_url,callback=self.parse_detail,meta={'item':item})

        if self.pageNum < 5:
            self.pageNum += 1
            new_url = format(self.url%self.pageNum)
            yield scrapy.Request(new_url,callback=self.parse)


    def parse_detail(self,response):
        #接收參數 response.meta
        item = response.meta['item']
        #簡介
        desc = response.xpath('/html/body/div[1]/div/div/div/div[2]/p[5]/span[2]/text()').extract_first()
        item['desc'] = desc
        yield item

View Code

setting.py

BOT_NAME = 'moviePro'

SPIDER_MODULES = ['moviePro.spiders']
NEWSPIDER_MODULE = 'moviePro.spiders'

# UA偽裝
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False
#輸出錯誤類型的日志
LOG_LEVEL = 'ERROR'


ITEM_PIPELINES = {
   'moviePro.pipelines.MovieproPipeline': 300,
}

View Code

items.py

import scrapy

class MovieproItem(scrapy.Item):
    # define the fields for your item here like:
    title = scrapy.Field()
    desc = scrapy.Field()

View Code

pipelines.py

class MovieproPipeline(object):
    def process_item(self, item, spider):
        print(item)
        return item

View Code

7.5scrapy中的中間件的應用

1.請求載體身份標識(可用)

user_agent_list = [
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 "
        "(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 "
        "(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 "
        "(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 "
        "(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 "
        "(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 "
        "(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 "
        "(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 "
        "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 "
        "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]

View Code

3.代理池(不可用)

PROXY_http = [
    '153.180.102.104:80',
    '195.208.131.189:56055',
]
PROXY_https = [
    '120.83.49.90:9000',
    '95.189.112.214:35508',
]

View Code

3.爬蟲中間件

4.下載中間件

作用 :批量攔截請求和響應

攔截請求

UA偽裝 :將所有的請求盡可能多的設定成不同的請求載體身份標識

代理操作

rom scrapy import signals
import random
user_agent_list = [
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.1 "
        "(KHTML, like Gecko) Chrome/22.0.1207.1 Safari/537.1",
        "Mozilla/5.0 (X11; CrOS i686 2268.111.0) AppleWebKit/536.11 "
        "(KHTML, like Gecko) Chrome/20.0.1132.57 Safari/536.11",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.6 "
        "(KHTML, like Gecko) Chrome/20.0.1092.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.6 "
        "(KHTML, like Gecko) Chrome/20.0.1090.0 Safari/536.6",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/537.1 "
        "(KHTML, like Gecko) Chrome/19.77.34.5 Safari/537.1",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/536.5 "
        "(KHTML, like Gecko) Chrome/19.0.1084.9 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.0) AppleWebKit/536.5 "
        "(KHTML, like Gecko) Chrome/19.0.1084.36 Safari/536.5",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 5.1) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_0) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1063.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1062.0 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.1 Safari/536.3",
        "Mozilla/5.0 (Windows NT 6.2) AppleWebKit/536.3 "
        "(KHTML, like Gecko) Chrome/19.0.1061.0 Safari/536.3",
        "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/535.24 "
        "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24",
        "Mozilla/5.0 (Windows NT 6.2; WOW64) AppleWebKit/535.24 "
        "(KHTML, like Gecko) Chrome/19.0.1055.1 Safari/535.24"
]

PROXY_http = [
    '153.180.102.104:80',
    '195.208.131.189:56055',
]
PROXY_https = [
    '120.83.49.90:9000',
    '95.189.112.214:35508',
]

# 下載中間件
class MovieproDownloaderMiddleware(object):

    # 攔截正常的請求,參數 request 就是攔截到請求對象
    def process_request(self, request, spider):
        print("i am process_request")
        #實現:將攔截到的請求盡可能多的設定成不同的請求載體身份標識
        request.headers['USER_AGENT'] = random.choice(user_agent_list)

        if request.url.split(":")[0] == "http":
            request.meta['proxy'] = 'http://' + random.choice(PROXY_http)
        else:
            request.meta['proxy'] = 'https://' + random.choice(PROXY_https)
        return None


    # 攔截響應,參數 request 就是攔截到響應
    def process_response(self, request, response, spider):
        print("i am process_response")
        return response

    # 攔截發生異常的請求
    def process_exception(self, request, exception, spider):
        print("i am process_exception")
        #攔截到異常的請求,然后對其進行修正,然后重新進行請求發送
        #代理操作
        if request.url.split(":")[0] == "http":
            request.meta['proxy'] = 'http://' + random.choice(PROXY_http)
        else:
            request.meta['proxy'] = 'https://' + random.choice(PROXY_https)
        #將修正后的請求進行重新發送
        return request

View Code

攔截響應

篡改響應數據或直接替換響應對象

需求 : 爬取網易新聞 國內,國際,軍事,航空,無人機這五個板塊下對應的新聞標題和內容

#分析:
1.每一個板塊對應的新聞數據是動態加載出來的

# selenium在scrapy中的應用:
    實例化瀏覽器對象:卸載爬蟲類的構造方法中

wangyi.py

import scrapy
from selenium import webdriver
from wangyiPro.items import WangyiproItem

class WangyiSpider(scrapy.Spider):
    name = 'wangyi'
    # allowed_domains = ['http://t.zoukankan.com/www.xxx.com']
    start_urls = ['https://news.163.com']

    five_model_urls = []
    #實例化一個瀏覽器對象
    bro = webdriver.Chrome(executable_path=r'E:飛秋爬蟲+數據	oolschromedriver.exe')
    #用來解析五個板塊對應的url,然后對齊進行手動請求發送
    def parse(self, response):
        model_index = [3,4,6,7,8]
        li_list = response.xpath('//*[@id="index2016_wrap"]/div[1]/div[2]/div[2]/div[2]/div[2]/div/ul/li')

        for index in model_index:
            li = li_list[index]
            #獲取五個板塊對應的url
            model_url = li.xpath('./a/@href').extract_first()
            self.five_model_urls.append(model_url)
            #對每個板塊的url進行手動請求發送
            yield scrapy.Request(model_url,callback=self.parse_model)

    #用作與解析每個板塊中的新聞標題和新聞詳情頁的url
    #問題:response(不滿足需求的response)沒有包含每一個板塊中動態加載的新聞數據
    def parse_model(self,response):
        div_list = response.xpath('/html/body/div/div[3]/div[4]/div[1]/div/div/ul/li/div/div')
        for div in div_list:
            title = div.xpath('./div/div[1]/h3/a/text()').extract_first()
            detail_url = div.xpath('./div/div[1]/h3/a/@href').extract_first()
            item = WangyiproItem()
            item['title'] = title
            #對詳情頁發起請求解析出新聞內容
            yield scrapy.Request(detail_url,callback=self.prase_new_detail,meta={'item':item})

    def prase_new_detail(self,response):
        item = response.meta['item']
        content = response.xpath('//*[@id="endText"]//text()').extract()
        content = ''.join(content)
        item['content'] = content
        yield  item

    #最后執行
    def closed(self,spider):
        self.bro.quit()

View Code

items.py

import scrapy

class WangyiproItem(scrapy.Item):
    # define the fields for your item here like:
    title = scrapy.Field()
    content = scrapy.Field()

View Code

middlewares.py

from scrapy import signals
from scrapy.http import HtmlResponse
from time import sleep

class WangyiproDownloaderMiddleware(object):

    def process_request(self, request, spider):

        return None

    # spider 就是爬蟲文件中爬蟲類實例化的對象
    def process_response(self, request, response, spider):
        #進行所有響應對象的攔截
        # 1.將所有響應對象中那五個不滿足需求的響應對象找出
            #每個響應對象對應唯一一個請求對象
            #如果我們定位到五個響應對象的請求對象后,就可以通過該請求對象定位到指定的響應對象
            #可以通過五個板塊的 url 定位請求對象
                #總結: url ==> request ==> response
        # 2.將找出的五個不滿足需求的響應對象進行修正(替換)

        #  spider.five_model_urls :五個板塊對應的url
        bro = spider.bro
        if request.url in spider.five_model_urls:
            bro.get(request.url)
            sleep(1)
            #包含了動態加載的新聞數據
            page_text = bro.page_source
            #如果if條件成立,則該response就是五個板塊對應的響應對象
            new_response = HtmlResponse(url=request.url,body=page_text,encoding='utf-8',request=request)
            return new_response
        return response

    def process_exception(self, request, exception, spider):
        pass

View Code

pipelines.py

class WangyiproPipeline(object):
    def process_item(self, item, spider):
        print(item)
        return item

View Code

setting.py

BOT_NAME = 'wangyiPro'

SPIDER_MODULES = ['wangyiPro.spiders']
NEWSPIDER_MODULE = 'wangyiPro.spiders'

# UA偽裝
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'

ROBOTSTXT_OBEY = False
LOG_LEVEL = 'ERROR'

DOWNLOADER_MIDDLEWARES = {
   'wangyiPro.middlewares.WangyiproDownloaderMiddleware': 543,
}

ITEM_PIPELINES = {
   'wangyiPro.pipelines.WangyiproPpeline': 300,
}

View Code

7.6.基于CrawSpider的全站數據爬取

CrawSpider簡介

CrawSpider就是爬蟲類中 Spider的一個子類

除了繼承到Spider的特性和功能外,還派生除了其自己獨有的更加強大的特性和功能。其中最顯著的功能就是”LinkExtractors鏈接提取器“。Spider是所有爬蟲的基類,其設計原則只是為了爬取start_url列表中網頁,而從爬取到的網頁中提取出的url進行繼續的爬取工作使用CrawlSpider更合適。

使用流程

1.創建一個基于CrawSpider的爬蟲文件 : 
    scrapy startproject sunPro
    cd sunPro
    scrapy genspider -t crawl spiderName http://t.zoukankan.com/www.xxx.com
2.構造鏈接提取器和規則解析器
    鏈接提取器
        作用:可根據指定的規則進行指定鏈接的提取
         提取規則:allow = '正則表達式'
    規則解析器
        作用:獲取鏈接提取器提取到的鏈接,然后進行請求發送,根據指定規則對請求到的頁面源碼數據進行數據解析
        follow = 'True' :將鏈接提取器 繼續作用到 鏈接提取器所提取到的頁碼鏈接所對應的頁面中 

7.6.1 基于CrawSpider的基本使用

數據鏈接地址 :http://wz.sun0769.com/index.php/question/questionType?type=4&page=

sun.py

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule

#未實現深度爬取:爬取的只是每個頁面對應的數據
class SunSpider(CrawlSpider):
    name = 'sun'
    # allowed_domains = ['http://t.zoukankan.com/www.xxx.com']
    start_urls = ['http://wz.sun0769.com/index.php/question/questionType?type=4&page=']
    #鏈接提取器  type=4&page=d+
    link = LinkExtractor(allow=r'type=4&page=d+')

    rules = (
        #實例化一個Rule(規則解析器)的對象
        Rule(link, callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        tr_list = response.xpath('//*[@id="morelist"]/div/table[2]//tr/td/table//tr')
        for tr in tr_list:
            title = tr.xpath('./td[2]/a[2]/@title').extract_first()
            status = tr.xpath('./td[3]/span/text()').extract_first()
            print(title,status)

View Code

setting.py

BOT_NAME = 'sunPro'

SPIDER_MODULES = ['sunPro.spiders']
NEWSPIDER_MODULE = 'sunPro.spiders'

# UA偽裝
USER_AGENT = 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/76.0.3809.132 Safari/537.36'

ROBOTSTXT_OBEY = False
LOG_LEVEL = 'ERROR'

View Code

7.6.2 基于CrawSpider的深度爬取

sun.py

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from sunPro.items import SunproItem,SunproItem_detail

class SunSpider(CrawlSpider):
    name = 'sun'
    # allowed_domains = ['http://t.zoukankan.com/www.xxx.com']
    start_urls = ['http://wz.sun0769.com/index.php/question/questionType?type=4&page=']
    #鏈接提取器
    link = LinkExtractor(allow=r'type=4&page=d+')

    #詳情頁url  question/201909/426989.shtml
    link_detail = LinkExtractor(allow=r'question/d+/d+.shtml')

    rules = (
        #實例化一個Rule(規則解析器)的對象
        Rule(link, callback='parse_item', follow=True),
        Rule(link_detail, callback='parse_datail'),
    )

    def parse_item(self, response):
        tr_list = response.xpath('//*[@id="morelist"]/div/table[2]//tr/td/table//tr')
        for tr in tr_list:
            title = tr.xpath('./td[2]/a[2]/@title').extract_first()
            status = tr.xpath('./td[3]/span/text()').extract_first()
            num = tr.xpath('./td[1]/text()').extract_first()
            item = SunproItem()
            item['title'] = title
            item['status'] = status
            item['num'] = num
            if num:
                yield item

    def parse_datail(self,response):
        content = response.xpath('/html/body/div[9]/table[2]/tbody/tr[1]//text()').extract()
        content = ''.join(content)
        num = response.xpath('/html/body/div[9]/table[1]/tbody/tr/td[2]/span[2]/text()').extract_first()
        if num:
            num = num.split(':')[-1]
            item = SunproItem_detail()
            item['content'] = content
            item['num'] = num
            yield item

View Code

pipelines.py

class SunproPipeline(object):
    def process_item(self, item, spider):

        if item.__class__.__name__ == "SunproItem_detail":
            content = item['content']
            num = item['num']
            print(content,num)
        else:
            title = item['title']
            status = item['status']
            num = item['num']
            print(title,status,num)

View Code

items.py

class SunproItem(scrapy.Item):
    title = scrapy.Field()
    status = scrapy.Field()
    num = scrapy.Field()

class SunproItem_detail(scrapy.Item):
    content = scrapy.Field()
    num = scrapy.Field()

View Code

7.7.分布式

7.7.1基本概念

什么是分布式爬蟲?

基于多臺電腦組建一個分布式機群,然后讓機群中的每一臺電腦執行同一組程序,然后讓它們對同一個網站的數據進行分布爬取

為什么要用分布式爬蟲?

提升爬取數據的效率

如何實現分布式爬蟲?

基于scrapy + redis 的形式實現分布式

scrapy 結合著 scrapy-redis組件實現分布式

原生的scrapy無法實現分布式原因?

調度器無法被分布式群共享

管道無法被共享

scrapy-redis組件的作用

提供可以被共享的調度器和管道

環境安裝:

pip insatll redis

pip install scrapy-redis

7.7.2分布式流程

#1.創建一個基于CrawSpider的爬蟲文件 : 
    scrapy startproject sunPro
    cd sunPro
    scrapy genspider -t crawl spiderName http://t.zoukankan.com/www.xxx.com
#2.修改當前的爬蟲文件
    1.導包 : from scrapy_redis.spiders import RedisCrawlSpider
       2.將當前爬蟲類的父類修改成RedisCrawlSpider
    3.將start_urls替換成redis_key = 'xxx'  #表示的是可被共享調度器中隊列的名稱
    4.編寫爬蟲類爬取數據的操作
#3.對setting進行操作 
    #指定管道
        開啟可被共享的管道 :
            ITEM_PIPELINES = {
                'scrapy_redis.pipelines.RedisPipeline': 400
                }
    #指定可被共享的調度器
    
# 增加了一個去重容器類的配置, 作用使用Redis的set集合來存儲請求的指紋數據, 從而實現請求去重的持久化
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis組件自己的調度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 配置調度器是否要持久化, 也就是當爬蟲結束了, 要不要清空Redis中請求隊列和去重指紋的set。如果是True, 就表示要持久化存儲, 就不清空數據, 否則清空數據
SCHEDULER_PERSIST = True  

    #指定redis服務
        REDIS_HOST = 'redis服務的ip地址'
        REDIS_PORT = 6379
        
#4.對redis配置文件進行配置 (redis.windows.conf)
    56行 :  #bind 127.0.0.1
    75行 :  protected-mode yes  --> protected-mode no
#5.攜帶配置文件啟動redis服務   redis-server .edis.windows.conf
    地址: E:飛秋爬蟲+數據	oolsedisRedis-x64-3.2.100
#6.啟動redis客戶端 :  redis-cli
#7.執行當前的工程
    進入到爬蟲文件對應的目錄中:scrapy runspider xxx.py
#8.向調度器隊列中仍入一個起始的url:
    隊列在哪里呢?
    答:隊列在redis中        lpush fbsQueue http://t.zoukankan.com/www.xxx.com

代碼

fbs.py

import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from scrapy_redis.spiders import RedisCrawlSpider
from fbsPro.items import FbsproItem

class FbsSpider(RedisCrawlSpider):
    name = 'fbs'
    # allowed_domains = ['http://t.zoukankan.com/www.xxx.com']
    # start_urls = ['http://http://t.zoukankan.com/www.xxx.com/']

    # redis_key表示的是可被共享調度器中隊列的名稱
    redis_key = 'fbsQueue'

    rules = (
        Rule(LinkExtractor(allow=r'type=4&page=d+'), callback='parse_item', follow=True),
    )

    def parse_item(self, response):
        tr_list = response.xpath('//*[@id="morelist"]/div/table[2]//tr/td/table//tr')
        for tr in tr_list:
            title = tr.xpath('./td[2]/a[2]/@title').extract_first()
            status = tr.xpath('./td[3]/span/text()').extract_first()

            item = FbsproItem()
            item['title'] = title
            item['status'] = status
            yield item

View Code

items.py

import scrapy


class FbsproItem(scrapy.Item):
    title = scrapy.Field()
    status = scrapy.Field()

View Code

settings.py

BOT_NAME = 'fbsPro'

SPIDER_MODULES = ['fbsPro.spiders']
NEWSPIDER_MODULE = 'fbsPro.spiders'

ROBOTSTXT_OBEY = True

#開啟可被共享的管道
ITEM_PIPELINES = {
    'scrapy_redis.pipelines.RedisPipeline': 400
}

#指定可被共享的調度器
# 增加了一個去重容器類的配置, 作用使用Redis的set集合來存儲請求的指紋數據, 從而實現請求去重的持久化
DUPEFILTER_CLASS = "scrapy_redis.dupefilter.RFPDupeFilter"
# 使用scrapy-redis組件自己的調度器
SCHEDULER = "scrapy_redis.scheduler.Scheduler"
# 配置調度器是否要持久化, 也就是當爬蟲結束了, 要不要清空Redis中請求隊列和去重指紋的set。如果是True, 就表示要持久化存儲, 就不清空數據, 否則清空數據
SCHEDULER_PERSIST = True

#指定redis服務
REDIS_HOST = '192.168.11.50'
REDIS_PORT = 6379

View Code

7.8 增量式爬蟲

總結

以上是生活随笔為你收集整理的python爬虫入门 之 移动端数据的爬取的全部內容,希望文章能夠幫你解決所遇到的問題。

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

主站蜘蛛池模板: 男人的天堂狠狠干 | 一本色道久久综合亚洲精品图片 | 天堂av官网 | 激情在线视频 | 泰国午夜理伦三级 | 色哟哟在线观看视频 | 蜜桃一区二区三区 | 国产日韩一区二区 | 中文在线√天堂 | 午夜性福利 | 骚婷婷 | 欧美成人精品激情在线视频 | 男女男精品视频站 | 玉足女爽爽91 | 日本精品网站 | 亚洲成人激情av | 一区二区三区在线播放视频 | 日日夜夜综合 | 亚洲第9页 | 国产一区二区三区四区五区在线 | 91黄视频在线观看 | 香蕉在线视频播放 | 黄色网址在线免费看 | 日韩激情影院 | 爽爽视频在线观看 | 黄色小视频在线看 | 日干夜操 | 欧美一区二区三区精品 | 激情小说综合 | 少妇捆绑紧缚av | 一二三四精品 | av色综合 | 黄av网| 亚洲最大综合网 | 久久精品一二区 | 国产精品久久久久毛片 | 97福利网 | 色拍拍视频 | 俄罗斯美女av | 91免费视频网站 | 国产91国语对白在线 | 中国精品一区二区 | 精品国产一区二区三区久久久 | 性欧美色图 | 亚洲欧美日韩网站 | 日韩国产一区 | 丰满双乳秘书被老板狂揉捏 | 男男h黄动漫啪啪无遮挡软件 | 欧美精品一区二区免费看 | 日韩精品一区二区三区国语自制 | 哺乳喂奶一二三区乳 | 欧美性猛交xxxx黑人 | 成人免费无码大片a毛片 | 91蜜桃传媒精品久久久一区二区 | 日本少妇ⅹxxxxx视频 | 男男gay羞辱feet贱奴vk | 青草国产 | 网站免费在线观看 | 日韩高清成人 | 亚洲 欧美 精品 | 欧美久久99| 精品国精品国产自在久不卡 | 91精品亚洲一区 | 亚洲h视频在线观看 | 精品人妻一区二区三区四区 | 亚洲精品国产精品国自产网站 | 樱花影院最新免费观看攻略 | 成人日批| 激情午夜视频 | 日韩中文字幕2019 | 日本中文字幕在线免费观看 | 久久久久久国产精品三级玉女聊斋 | 亚洲偷偷 | 91久久久久久 | av男人网| 久操热| 亚洲视频h| 国产夫妻性爱视频 | 白嫩初高中害羞小美女 | 一本大道东京热无码aⅴ | 日韩亚洲第一页 | av大片网| 在线亚洲天堂 | 尤物视频免费观看 | 国产乱一区二区三区 | 亚洲欧美视频在线 | 日本中文在线播放 | 亚洲成人va| 欲色网站| 亚洲夜夜夜 | 日本学生初尝黑人巨免费视频 | 天堂网av2014 | 美国少妇在线观看免费 | 中文一区在线 | 先锋影音av资源在线 | 91精品在线免费观看 | 免费毛毛片 | 欧美夜夜夜 | 久久午夜激情 |