一区二区三区在线-一区二区三区亚洲视频-一区二区三区亚洲-一区二区三区午夜-一区二区三区四区在线视频-一区二区三区四区在线免费观看

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - python scrapy拆解查看Spider類爬取優設網極細講解

python scrapy拆解查看Spider類爬取優設網極細講解

2022-03-01 00:26夢想橡皮擦 Python

本篇博客為你帶來 scrapy.Spider 模塊中的相關函數與類,帶你再一次認識 scrapy 的細節。本次采集的目標站點為:優設網,有需要的朋友可以借鑒參考下

拆解 scrapy.Spider

本次采集的目標站點為:優設網

每次創建一個 spider 文件之后,都會默認生成如下代碼:

?
1
2
3
4
5
6
7
8
import scrapy
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['http://www.uisdc.com/']
 
    def parse(self, response):
        self.log()

繼承的基類 scrapy.Spider 自然就成了我們要研究的第一個內容,進入其源碼,發現如下內容。

scrapy.Spider 核心實現的是 start_requests 方法

Spider 主要進行的操作就是初始化 Request 請求,而這些都是通過 start_requests 實現的,詳細代碼為:

?
1
2
for url in self.start_urls:
    yield Request(url, dont_filter=True)

start_requests 方法,你可以自己編寫同名函數覆蓋修改,編寫時發現了 make_requests_from_url 方法,該方法在最新版本的 scrapy 中已經被廢除。

重寫 start_requests 方法 ,需要注意重寫時,必須返回一個可迭代對象,并且該對象包含 spider 用于爬取的第 1 個 Request,由于 scrapy 只調用一次該方法,所以你可以將登錄站點請求放置到該方法中。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
import scrapy
from scrapy.http import Request
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['http://www.uisdc.com/']
 
    def start_requests(self):
        print("重寫 start_requests")
        yield Request(self.start_urls[0])
 
    def parse(self, response):
        print(response)

將登錄信息放置到 start_requests 中,代碼如下:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
import scrapy
from scrapy.http import FormRequest
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['http://www.uisdc.com/']
 
    def start_requests(self):
        print("手動 start_requests")
        yield FormRequest("https://httpbin.org/post", formdata={"user": "ca"}, callback=self.parse)
 
    def parse(self, response):
        print(response.text)

scrapy.Spider 屬性值

name 屬性:

表示爬蟲名稱,spider 的名稱用于 scrapy 定位爬蟲,所以非常重要,一般常見的名稱方式是使用網站域名(domain),命名 spider,例如 baidu.com 命名為 baidu,但是工作喜歡還是攜帶 .com 后綴。

allowed_domains 屬性:

該屬性需要配置 offsiteMiddleware 使用,當該中間件啟用之后,待采集 URL 的域名如果不在 allowed_domains 列表中,會被禁止訪問。
domains 內容添加,假設你的目標 URL 是 http://www.baidu.com/123.html,僅填寫 baidu.com 即可。

start_urls 屬性:

起始的 URL 列表,主要用于 start_request 方法進行迭代。

custom_settings 屬性:
自定義配置,可以覆蓋 settings.py 的配置,以字典格式賦值。

?
1
2
3
custom_settings = {
    "ROBOTSTXT_OBEY": False # 不請求 robot.txt 文件
}

crawler 屬性:

該屬性在爬蟲啟動后,由類方法 from_crawler() 設置。

settings 屬性:

指定配置文件的實例。

logger 屬性:

spider 日志輸出對象,默認以 spider 名稱創建,可以自定義。

?
1
2
self.logger.info('輸出響應地址 %s', response.url)
logger.info('輸出響應地址 %s', response.url)

補充一下 scrapy 日志級別

settings.py 中設置 log 級別,只需要增加一行代碼:

?
1
LOG_LEVEL = 'WARNING'

設置為 WARNING 級別,會發現 scrapy 默認的各種調試信息,都不在控制臺輸出。

scrapy 日志級別與 logging 模塊一致。

CRITICAL:嚴重錯誤;

ERROR :一般錯誤;

WARNING: 警告信息;

INFO :一般信息;

DEBUG:調試信息。

scrapy 中的 settings 中關于日志的配置如下:

LOG_ENABLED:默認: True,表示啟用 logging;

LOG_ENCODING: 默認: utf-8,logging 使用的編碼;

LOG_FILE 默認: None,日志保存的文件名;

LOG_LEVEL: 默認 DEBUG ,log 的最低級別。

scrapy.Spider 實例方法與類方法

from_crawler 類方法
在查看源碼之后,該方法的功能會比較清晰。

?
1
2
3
4
5
6
7
8
9
10
@classmethod
def from_crawler(cls, crawler, *args, **kwargs):
    spider = cls(*args, **kwargs)
    spider._set_crawler(crawler)
    return spider
 
def _set_crawler(self, crawler):
    self.crawler = crawler
    self.settings = crawler.settings
    crawler.signals.connect(self.close, signals.spider_closed)

該方法設置了 crawlersettings 兩個屬性,該方法在上一篇博客已經有所涉及,直接回顧即可。

parse 方法
當請求(Request)沒有指定回調參數(callback)時,該方法是 scrapy 用來處理響應的默認回調方法。

log 方法
使用 self.log() 方法記錄日志。

學習到這里,對 Spider 模塊有了一個比較整體的認識。

爬取優設網

接下來進入爬蟲采集相關代碼編寫,有了前文知識鋪墊之后,采集代碼就變得非常簡單了。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
import scrapy
from uisdc.items import UisdcItem
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['https://www.uisdc.com/archives']
    custom_settings = {
        "ROBOTSTXT_OBEY": False
    }
 
    def parse(self, response):
        # print(response.text)
        # self.log("測試是否有數據輸出", logging.WARNING)
        items = response.xpath('//div[@id="archive_list"]/div/div[1]/div[1]/div[contains(@class,"item-article")]')
        for i in items:
            item = UisdcItem()
            title = i.xpath(".//h2[@class='item-title']/a/text()").extract_first()
            author = i.xpath(".//h3[@class='meta-name']/text()").extract_first()
            tag = i.xpath(".//div[@class='meta-tag']/a/text()").extract_first()
            item["title"] = title
            item["author"] = author
            item["tag"] = tag
            yield item

接下來修改源碼,增加 ** Item Loaders** 填充容器機制。通過 from scrapy.loader import ItemLoader 導入新類,該類的構造函數如下:

?
1
def __init__(self, item=None, selector=None, response=None, parent=None, **context)

其中 item 是容器類,selector 為 Selector 對象,提取填充數據的選擇器,response 為 Response 響應對象。

代碼修改之后得到如下代碼:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
import scrapy
from uisdc.items import UisdcItem
from scrapy.loader import ItemLoader
class UiSpider(scrapy.Spider):
    name = 'ui'
    allowed_domains = ['www.uisdc.com']
    start_urls = ['https://www.uisdc.com/archives']
    custom_settings = {
        "ROBOTSTXT_OBEY": False
    }
    def parse(self, response):
        items = response.xpath('//div[@id="archive_list"]/div/div[1]/div[1]/div[contains(@class,"item-article")]')
        for i in items:
            l = ItemLoader(item=UisdcItem(), selector=i)
            l.add_xpath('title', ".//h2[@class='item-title']/a/text()")
            l.add_xpath('author', ".//h3[@class='meta-name']/text()")
            l.add_xpath('tag', ".//div[@class='meta-tag']/a/text()")
            yield l.load_item()

其中需要注意 l = ItemLoader(item=UisdcItem(), selector=i) 使用 selector 參數,并賦值為迭代變量 i,如果使用 response 會得到重復數據。

最后,當所有數據被收集起來之后, 調用 ItemLoader.load_item() 方法, 返回 Item 對象。

輸出 item 對象,發現每一個數據都是列表。

?
1
2
3
{'author': ['土撥鼠'],
 'tag': ['產品設計'],
 'title': ['6000+干貨!資深總監的四條產品設計工作觀(附私藏神器包)']}

接下來需要處理每一項的值,ItemLoader 得到的數據,在存入 item 容器前,是支持對數據進行預處理的,即輸入處理器和輸出處理器,修改 items.py 文件。

?
1
2
3
4
5
6
7
8
9
10
11
12
from scrapy.item import Item, Field
from scrapy.loader.processors import MapCompose, TakeFirst
def ext(value):
    return "新聞:" + value
class UisdcItem(Item):
    # define the fields for your item here like:
    title = Field(
        input_processor=MapCompose(ext),
        output_processor=TakeFirst()
    )
    author = Field(output_processor=TakeFirst())
    tag = Field(output_processor=TakeFirst())

Field 字段的兩個參數:

輸入處理器(input_processor):可以在傳進來的值做一些預處理。

輸出處理器(output_processor) :輸出值前最后的一步處理。

其中用到了 TakeFirst(),返回第一個非空(non-null/ non-empty)值,常用于單值字段的輸出處理器,無參數。

還用到了 MapCompose,能把多個函數執行的結果按順序組合起來,產生最終的輸出,通常用于輸入處理器。

其余內置的處理器如下

Identity:不進行任何處理,返回原來的數據,無參數;

Join:返回用分隔符連接后的值,分隔符默認為空格;

Compose:用給定的多個函數的組合,來構造處理器,list 對象一次被傳遞到各個函數中,由最后一個函數返回整個處理器的輸出,默認情況下遇到 None值(list 中有 None 值)的時候停止處理,可以通過傳遞參數 stop_on_none = False 改變這種行為;

MapCompose:輸入值是被迭代的處理的,List 對象中的每一個元素被單獨傳入,依次執行對應函數。

關于 item loader 還有一些其它的知識點,我們后面再聊。

以上就是python scrapy拆解查看Spider類爬取優設網極細講解的詳細內容,更多關于scrapy拆解Spider類爬取優設網的資料請關注服務器之家其它相關文章!

原文鏈接:https://blog.csdn.net/hihell/article/details/120936534

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 91动漫在线观看 | 亚洲国产成人精品无码区APP | 国产精品久久久久久久久齐齐 | 日韩一区二区三区四区区区 | 日本人护士免费xxxx视频 | 99久久免费国产特黄 | 大团圆免费阅读全文 | 欧美人在线一区二区三区 | 亚洲国产精品综合久久一线 | 国产美女操 | 午夜国产精品 | 无码任你躁久久久久久久 | 色五夜婷婷 | 99热导航| 欧美搞逼视频 | 性欧美videofree中文字幕 | 91在线一区二区三区 | 国产国语在线播放视频 | naruto tube18动漫| 精品国产欧美一区二区五十路 | 亚洲美色综合天天久久综合精品 | 四缺一写的小说 | 国产一区二区三区四卡 | 午夜精品亚洲 | 亚洲AV人无码综合在线观看蜜桃 | 日本九九视频 | 5x社区发源地最新地址 | 日本妻子迷妹网 | 欧美伊香蕉久久综合类网站 | 亚洲AV午夜福利精品香蕉麻豆 | 国产国语videosex另类 | 亚洲精品午夜久久aaa级久久久 | 国产a不卡片精品免费观看 国产aaa伦理片 | 动漫美女日批 | 日本十大顶级绝伦推理片 | 国产老熟 | 国产中文在线视频 | 日韩视频在线免费观看 | 闺蜜高h| 四虎www| 99精品久久精品一区二区小说 |