久久国产成人av_抖音国产毛片_a片网站免费观看_A片无码播放手机在线观看,色五月在线观看,亚洲精品m在线观看,女人自慰的免费网址,悠悠在线观看精品视频,一级日本片免费的,亚洲精品久,国产精品成人久久久久久久

分享

Python爬蟲Scrapy筆記

 小生凡一 2021-11-30

Scrapy 框架

這邊是高級篇,基礎篇在另一篇博客
https://blog.csdn.net/weixin_45304503/article/details/105581137

scrapy自帶多線程,所以效率特別高

1. 框架原理

在這里插入圖片描述

2. 安裝

  • windows下

    法一:

    pip3 install -i https://pypi.tuna./simple scrapy
    

    現(xiàn)在直接安裝就行了,但是去年直接安裝會報錯…所以去年用的是法二

    法二:
    安裝scrapy以及pypiwin32 (用輪子裝,win系統(tǒng)下要安裝pypiwin32)

  • linux下

    如果是在ubuntu下,還需要安裝第三方庫

    sudo apt-get install python-dev python-pip libxm12-dev libxslt1-dev zlib1g-dev libffi-dev libssl-dev
    

3. 創(chuàng)建

  1. 創(chuàng)建項目:'scrapy startproject [爬蟲的名字]’ (記得進入pycharmprojects的頁面來進行創(chuàng)建)

  2. 創(chuàng)建爬蟲:進入到項目所在的路徑,執(zhí)行命令:'scrapy genspider [爬蟲的名字] [爬蟲的域名]’ 放在spider上創(chuàng)建

4. 結構

  • items.py:用來存放爬蟲爬取下來的數(shù)據(jù)類型
  • middlewares.py:用來存放各種中間件的文件
  • pipelines.py:用來將items的模型存儲到本地磁盤中
  • settings.py:本爬蟲的一些配置信息(比如請求頭,、多久發(fā)送一次,、ip代理池等等)
  • scrapy.cfg:項目的配置文件
  • spiders包:以后所有的爬蟲,都是存放到這里面

5. 知識

5.1 基本知識:

  • response是一個scrapy.http.response.html.HtmlResponse對象,可以執(zhí)行xpathcss語法來提取數(shù)據(jù)。

  • 提取出來的數(shù)據(jù),是一個Selector或者是一個SelectorList對象,。如果想要獲取其中的字符串,那么應該執(zhí)行getall或是get方法

  • getall方法:獲取selector中的所有文本,返回的是列表,。

  • get方法:獲取selector中的第一個文本,返回的是str類型

  • 如果數(shù)據(jù)解析回來,要傳給pipline處理,。那么可以使用yield關鍵字來返回,或是可以收集到所有的item,最后統(tǒng)一使用return返回,。

  • item:建議在item.py中定義好模型,以后就不要使用字典了,在最后將數(shù)據(jù)變成字典就行了

  • pipeline:這個是專門用來保存數(shù)據(jù)的,其中三個方法是會經(jīng)常用到的。

? open_spider(self,spider):當爬蟲被打開的時候就會被調(diào)用

? process_item(self,item,spider):當爬蟲有item傳過來的時候就會被調(diào)用

? close_spider(self,spider):當爬蟲關閉的時候會被調(diào)用
要激活piplilne , 應該在settings.py中設置ITEM_PIPELINES將其激活.

  • JsonItemExporter:這個是每次把數(shù)據(jù)添加到內(nèi)存中,最后統(tǒng)一寫入到磁盤中
    1. 好處就是存儲的數(shù)據(jù)是一個滿足json規(guī)則的數(shù)據(jù),。
    2. 壞處就是如何數(shù)據(jù)量比較大,那么比較消耗內(nèi)存,。
from scrapy.exporters import JsonItemExporter   # 導入json導出器

class QsbkPipeline(object):
    def __init__(self):
        self.fp=open("duanzi.json",'wb')  # 以二進制的方式打開
        self.exporter=JsonItemExporter(self.fp, ensure_ascii=False,encoding='utf-8')  # 創(chuàng)建一個導入的對象
        self.exporter.start_exporting()  # 開始導入


    def open_spider(self,spider):  # 爬蟲開始
        print("爬蟲開始")

    def process_item(self, item, spider):  # item是爬蟲返回的數(shù)據(jù)
        self.exporter.export_item(item)  # 用export_item來進行返回
        return item

    def close_spider(self,spider): #爬蟲結束
        self.exporter.finish_exporting()
        self.fp.close()
        print("爬蟲結束了")
  • JsonLinesItemExporter:這個是每次調(diào)用export_item的時候就吧這個item存儲到硬盤當中。
    1. 壞處是每一個字典是一行,整個文件不是一個滿足json格式的文件,。
    2. 好處就是每次處理數(shù)據(jù)的時候就直接存儲到硬盤當中,這樣不會消耗內(nèi)存,數(shù)據(jù)也比較安全,。
from scrapy.exporters import JsonLinesItemExporter   
# 導入json導出器,有l(wèi)ines, 一行一行的來,數(shù)據(jù)量多的話就用這個

class QsbkPipeline(object):
    def __init__(self):
        self.fp=open("duanzi.json",'wb')  # 以二進制的方式打開
        self.exporter=JsonLinesItemExporter(self.fp, ensure_ascii=False,encoding='utf-8') 
            # 創(chuàng)建一個導入的對象
            # 這邊不需要開始導入之類的
    def open_spider(self,spider):  # 爬蟲開始
        print("爬蟲開始")

    def process_item(self, item, spider):  # item是爬蟲返回的數(shù)據(jù)
        self.exporter.export_item(item)  # 用export_item來進行返回
        return item

    def close_spider(self,spider): #爬蟲結束
        # self.exporter.finish_exporting()  也不需要什么結束導入
        self.fp.close()
        print("爬蟲結束了")

5.2 創(chuàng)建CrawlSpider爬蟲:

scrapy genspider -c crawl [爬蟲名字] [域名]

5.3 LinkExtractors連接提取器:

這個可以不用程序員自己提取想要的url,然后發(fā)送請求。這些工作可以交給LinkExtractors,他會在所有爬取的網(wǎng)面中找到滿足規(guī)則的url,實現(xiàn)自動的爬取,。

class scrapy.linkextractors.LinkExtractor(
allow=(),    #允許的url  所有滿足這個正則表達式的url都會被提取
    deny=(), #禁止的url  所有滿足這個正則表達式的url都不會被提取
    allow_domains(),  #允許的域名  只有在這個里面指定的域名的url才會被提取
    deny_extensions=None, 
    restrict_xpaths=(),  # 嚴格的xpath和allow共同過濾鏈接
    tahs=('a','area'),
    attrs=('herf'),
    unique=True,
    process_value=None
)

5.3 Rule規(guī)則類:

class scrapy.spiders.Rule(
link_extractor,
    callback=None, #滿足這個規(guī)則的url就應該執(zhí)行哪個回調(diào)函數(shù).因為CrawlSpider使用了parse作為回調(diào)函數(shù),因此不要副高parse作為回調(diào)函數(shù)自己的回調(diào)函數(shù)
    cb_kwargs=None, 
    follow=None,   # 是否需要跟進默認True
    process_links=None,   # 從link_extractor中獲取到連接后會傳遞給這個函數(shù),用來過濾不需要爬取的連接
    process_request=None  
)

CrawlSpider:

需要使用LinkExtractor和Rule這兩個東西決定爬蟲給的具體走向

1.allow設置規(guī)則的方法:要能夠限制在我們想要的url上面,不要跟其他url產(chǎn)生相同的正則表達式即可,。

2.什么情況下使用follow:如果在爬取頁面的時候,需要將滿足當前條件的url再進行跟進,那么就設置為True。否則設置為False.

3.什么情況下該指定callback:如果這個url對應的頁面,只是為了獲取更多的url,并不需要里面的數(shù)據(jù),那么可以不指定callback,。如果想要獲取url對應的頁面中的數(shù)據(jù),那么就需要指定一個callback來進行數(shù)據(jù)的處理,儲存等,。

關于Scrapy Shell

再爬蟲中使用xpath,beautifulsoup,正則表達式,css選擇器等等,但是scrapy是一個比較重的框架,每次運行起來都要等待一段時間,因此要去驗證我們寫的提取規(guī)則是否正確,是一個麻煩的事情,因此scrapy提供了一個shell可以方便測試規(guī)則。

在cmd打開終端,進入到scrapy項目所在的目錄,然后進入到scrapy框架所在的虛擬環(huán)境中,輸入命令,scrapy shell 鏈接,。就會進入到scrapy的shell環(huán)境中,你可以跟在爬蟲中的parse方法一樣使用了,。

1.可以方便我們做一些數(shù)據(jù)提取的測試代碼

2.如果想要執(zhí)行scrapy命令,那么毫無疑問,肯定是要想進入scrapy所在的環(huán)境中,我自己電腦的python環(huán)境只有一個,是定義到全局的,所以就可以直接進行命令

3.如果想要讀取某個項目的配置信息,那么應該先進入到這個項目中。再執(zhí)行’scrapy shell’命令

Request和Response對象

1.Request對象

class Request(object_ref):

    def __init__(self, url, callback=None, method='GET', headers=None, body=None,
                 cookies=None, meta=None, encoding='utf-8', priority=0,
                 dont_filter=False, errback=None, flags=None, cb_kwargs=None):

        self._encoding = encoding  # this one has to be set first
        self.method = str(method).upper()
        self._set_url(url)
        self._set_body(body)
        assert isinstance(priority, int), "Request priority not an integer: %r" % priority
        self.priority = priority

        if callback is not None and not callable(callback):
            raise TypeError('callback must be a callable, got %s' % type(callback).__name__)
        if errback is not None and not callable(errback):
            raise TypeError('errback must be a callable, got %s' % type(errback).__name__)
        self.callback = callback
        self.errback = errback

        self.cookies = cookies or {}
        self.headers = Headers(headers or {}, encoding=encoding)
        self.dont_filter = dont_filter

        self._meta = dict(meta) if meta else None
        self._cb_kwargs = dict(cb_kwargs) if cb_kwargs else None
        self.flags = [] if flags is None else list(flags)

Request對象在我們寫爬蟲,爬取一頁的數(shù)據(jù)需要重新發(fā)送一個請求的時候調(diào)用,。這個類需要傳遞一些參數(shù),其中比較常用的參數(shù)有:

1.url:這個request對象發(fā)送請求的url,。

2.callback:在下載器下載完相應的數(shù)據(jù)后執(zhí)行的回調(diào)函數(shù)。

3.method:請求的方法,。默認為GET方法,可以設置為其他方法,。

4.headers:請求頭,對于一些固定的設置,放在settings.py中指定就可以了。對于那些非固定的,可以在發(fā)送請求的時候指定,。

5.meta:比較常用,。用于在不同的請求之間傳遞數(shù)據(jù)用的。

6.encoding:編碼,默認的為utf-8,使用默認的就可以了

7.dot_filter:表示不由調(diào)度器過濾,在執(zhí)行多次重復的請求的時候用得比較多,。比如驗證碼,。

8.errback:在發(fā)生錯誤的時候執(zhí)行的函數(shù)

2.Response對象

Response對象一般是有scrapy給你自動構建的。因此開發(fā)者不需要關心如何創(chuàng)建response對象,而且如何使用他,。response對象有很多屬性,可以用來提取數(shù)據(jù)的,。主要有一下屬性

1.meta:從其他請求傳過來的meta屬性,可以用來保持多個請求之間的數(shù)據(jù)連接。

2.encoding:返回當前字符串編碼和解碼的格式

3.text:將返回的數(shù)據(jù)作為unicode字符串返回

4.body:將返回來的數(shù)據(jù)作為bytes字符串返回

5.xpath:xpath選擇器

6.css:css選擇器

發(fā)送POST請求:

如果需要post請求的話,就需要使用request的子類fromrequest來實現(xiàn),如果想要在爬蟲一開始的時候就發(fā)送給post請求的話,那么需要在爬蟲類中重寫start_requests(self)方法,并且不再調(diào)用start_urls里的url.

3.模擬登陸人人網(wǎng)

1.想發(fā)送post請求,那么推薦使用scrapy.FormRequest方法,??梢苑奖愕闹付ū韱螖?shù)據(jù)

2.如果想在爬蟲一開始的時候就發(fā)送post請求,那么應該重寫start_requests方法,發(fā)送請求

4.模擬登陸豆瓣

下載圖片和文件

scrapy為下載item中包含的文件,提供了一個可重用的item pipelines。這寫pipeline有些共同的方法和結構,我們稱之為media pipeline。一般使用files pipeline或是images pipeline

好處:

1.避免重復下載過的文件

2.可以方便指定下載文件的存儲路徑

3.可以將下載的圖片轉換成通用的格式,比如png或是jpg

4.可以方便的生成縮量圖

5.可以方便的檢測圖片的寬和高,確保他們滿足最小限制

6.異步下載,效率非常高

下載文件的Files Pipeline:

使用Files Pipeline下載文件的話,按照一下步驟來完成

1.定義好一個Item,然后再這個item中定義兩個屬性,分別是file_urls以及files,。file_urls是用來存儲需要下載的文件的url鏈接,需要給一個列表,。

2.當文件下載完成后,會把文件下載的相關信息存儲到item的files屬性中。比如下載路徑,下載的url和文件的效驗碼等,。

3.再配置文件settings.py中配置FILES_STORE,這個配置是用來設置文件下載下來的路徑

4.啟動pipeline:再ITEM_PIPELINES中設置scrapy.pipelines.files.FilesPipeline:1

下載圖片的Images Pipeline:

但是用Images Pipeline下載文件的時候,按照一下步驟來完成:

1.定義好一個Item,然后再這個item中定義兩個屬性,分別為image_urls以及images,。images_urls

是用來儲存需要下載的圖片的url鏈接,需要給一個列表。

2.當文件下載完成后,會把文件下載的相關信息存儲到item的images屬性中,。比如下載路徑,、下載的url和圖片的校驗碼等

3.再配置文件settings.py中配置IMAGES_STORE,這個配置是用來設置圖片下載下來的路徑

4.啟動pipeline:在ITEM_PIPELINES中設置scrapy.pipelines.images.ImagesPipeline:1

下載器中間件:
Downloader Middlewares:

下載器中間件是引擎和下載器之間通信的中間將。在這個中間件中,。我們可以設置代理,更換請求頭等來達到反發(fā)爬蟲的目的,。要寫中間器,可以在下載器中實現(xiàn)兩個方法。一個是process_request(self,request,spider),這個方法是在請求發(fā)送之前會執(zhí)行的,還有一個是process_response(self,request,reponse,spider),這個方法是數(shù)據(jù)下載到引擎之前執(zhí)行,。

process_request(self,request,spider):

這個方法是下載器在發(fā)送請求之前會執(zhí)行的,。一般可以在這個里面設置一些隨機代理ip

1.參數(shù):

? 。request:發(fā)送請求request對象

? ,。spider:發(fā)送請求的spider對象

2.返回值:

? ,。返回None:如果返回None,Scrapy將繼續(xù)處理該request,執(zhí)行其他中間件中的相應方法,知道合適的下載器處理函數(shù)被調(diào)用。

? ,。返回Response對象:Scrapy將不會調(diào)用任何其他的process_request方法,將直接返回這個response對象,。已經(jīng)激活的中間件process_reponse()方法則會在每個response返回時被調(diào)用。

? ,。 返回Request對象:不再使用之前的request對象去下載數(shù)據(jù),而是使用現(xiàn)在的request對象返回數(shù)據(jù)

? 。如果這個方法拋出異常,則會調(diào)用process_exception方法,。

process_response(self,request,spider):

1.參數(shù):

? ,。request:request對象

? 。response: response對象

? ,。spider:spider對象

2.返回值:

? ,。返回Response對象:會將這個新的response對象傳給其他中間件,最終傳給爬蟲

? 。 返回Request對象:下載器鏈被切斷,返回的request會重新被下載器調(diào)度下載

? ,。如果這個方法拋出異常,則會調(diào)用request的errback方法,如果沒有指定這個方法,就會拋出一個異常

隨機請求頭:

如果一直都是用一個請求頭,那么可能會被服務器抓到的,。所以就要用到很多的請求頭。

http://www./pages/useragentstring.php

這個網(wǎng)址上面的有許多請求頭,而且都是比較新的!舒服

代理ip

建議就是芝麻代理,。

6. 分布式爬蟲

scrapy 是一個框架,但是本身就不支持分布式的,就是要加上scrapy-redis

Advantage:
1.可以充分利用多臺機器的帶寬
2.可以充分利用多臺機器的ip地址
3.多臺機器做,爬取效率高,。

Problem:
1.分布式爬蟲是好多臺機器再同時運行,如何保證不同的機器爬取亞眠的時候不會出現(xiàn)重復爬取的問題。
2.同樣,分布式爬蟲在不同的機器運行,在把數(shù)據(jù)爬完后如何保存在同一個地方,。

Redis

redis是一種支持分布式的nosql數(shù)據(jù)庫,是非關系型數(shù)據(jù)庫,同時的保存在內(nèi)存當中,同時redis可以定時把內(nèi)存數(shù)據(jù)同步到磁盤,既可以將數(shù)據(jù)持久化.比memcached支持更多的數(shù)據(jù)結構

1. 啟動redis:

sudo service redis-server start

2.連接上redis-server

redus-cli -h [ip] -p [端口]

3.添加

set key value

eg:set username xiaotou
?
將字符串值value關聯(lián)到key,。如果key已經(jīng)持有其他值,set命令就復寫舊值,無視其類型。并且默認的時期時間是永久,即永遠不會過期,。

4.刪除:

del key

eg:del username

5.設置過期時間:

expire key timeout  (秒)

6.列表操作:

  1. 在列表的左邊添加元素:
lpush key value

?將值value插入到列表key的表頭中,如果key不存在,一個空列表會被創(chuàng)建并執(zhí)行l(wèi)push操作,。當key存在當不是列表類型是,將返回一個錯誤.

  1. 在列表右邊添加元素:
lpush key value

?將值value插入到列表key的表尾,。如果key不存在,一個空列表會被創(chuàng)建并執(zhí)行rpush的操作。當key存在當不是列表類型是,返回一個錯誤,。

  1. 查看列表中的元素
lrange key start stop

返回列表key中指定區(qū)間內(nèi)的元素,區(qū)間以偏移量start和stop指定
如果要左邊的第一個到最后一個lrange key 0-1, 0是第一個,。-1是最后一個

  1. 移除列表中的元素:

?1)移除并返回列表key的頭元素

lpop key

?2)移除并返回列表的尾元素

rpop key

?3)移除并返回列表的中的元素

lrem key count value

?將刪除key這個列表中,count個值為value
?4)指定返回第幾個元素

lindex key index

將返回key這個列表中索引index這個元素

? 5)獲取列表中的元素個數(shù)

llen key

eg:llen langueage
6)刪除指定元素

lrem key count value
eg: lrem languages 0 php

根據(jù)參數(shù)count的值,移除列表中與參數(shù)value相等的元素。count的值可以是一下幾種
count>0:從表頭開始向表尾搜索,移除與value相等的元素,數(shù)量是count
count<0:從表尾開始先表頭搜索,移除與value相等的元素,數(shù)量為count的絕對值
count=0:移除表中所有與value相等的值

7.set集合操作

1.添加元素

sadd set value1 value2
eg: sadd team xiaotuo datuo

2.查看元素

smembers set
eg: smember set

3.移除元素

srem set member...
eg : srem team xiaotuo datuo

4.查看集合中的元素個數(shù)

scard set
eg:scard teaml

5.獲取多個集合的交集

sinter set1 set2
eg: sinter team1 team2

6.獲取多個集合的并集

sunion set1 set2
eg:sunion team1 team2

7.獲取多個集合的差集

sdiff set1 set2
eg:sdiff team1 team2

8.hash哈希操作

redis中的字典,。
1.添加新值

hset key field value
eg:hset website baidu baidu.com

2.獲取哈希中的field對應的值

hget key field
eg:hget website baidu

3.刪除field中的某個field

hdel key field
eg:hdel website baidu

4.獲取某個哈希中所有的field和value

hgetall key
eg:hgetall website 

5.獲取某個哈希中所有的值

hvals key
eg:hvals website

6.判斷哈希中是否存在某個field

hexists key field
eg:hexists website baidu

7.獲取哈希中總共的鍵值對

hlen field
eg:hlen website

    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多