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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

Scrapy中的yield使用

發布時間:2023/12/15 编程问答 30 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Scrapy中的yield使用 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Scrapy中yield的使用

  • 背景
  • yield的理解
  • scrapy中的yield的使用
    • scrapy.Request對象
    • scrapy.Item對象
  • scrapy中的傳值的問題
    • 從持久化數據源(數據庫/表格)中獲取數據
    • 使用cb_kwargs在request和callback回調函數之間進行傳參
  • 參考

背景

yield和協程總是相伴出現。
scrapy使用yield進行數據解析和爬取request。

yield的理解

yield的解釋都比較復雜,一段典型的yield的使用如下:

def foo(): print("starting...")while True:res = yield 4print("res:",res) g = foo() print(next(g)) print("*"*20) print(g.send(7))

這邊有幾個要點:

  • yield的一行跟return的用法基本比較接近;
  • 含yield的函數(foo)被稱為++生成器++;
  • res = yield 4處包含了4個操作
  • 向調用處拋出(返回)4
  • 暫停,并等待調用處的next或send恢復
  • 接收調用處send發送進來的值
  • 將接收到的值賦給等號左邊
  • 生成器接收到next或send恢復后,從yield的下一句開始執行,
  • 本例中調用next恢復后,從yield處繼續往下執行,其中next調用帶入的參數為None,因此從執行res = None繼續往下;
  • 本例中調用send恢復后,從yield處繼續往下執行,其中yield在生成器的返回值為send帶入的參數7
  • scrapy中的yield的使用

    在scrapy中典型的yield場景主要是使用scrapy.Request對象和scrapy.Item對象。

    scrapy.Request對象

    def start_requests(self):urlfront = 'http://www.example.com/XYPT/score/scoreInfoList?objectType=1&pageSize=100&scoreUnitId='csv_reader = csv.reader(open("./Requirement.csv"))for line in csv_reader:#根據數據生成爬取地址url = urlfront + self.punishment_numberyield scrapy.Request(url=url, callback=self.parse2)

    scrapy框架會去獲得Requese對象指向的鏈接,并進行爬取請求,在請求完成后調用該對象的回調函數。
    這里我們查表獲取鏈接,并拼裝,在循環內通過yield來發起請求,并且還將函數parse2注冊為回調函數,parse2中應提取響應所需的數據。

    scrapy.Item對象

    #存儲結構化數據 for company in response.css('tbody').css("tr"):field = company.css("td")yield {'Number': field[0].css("::text").get(),'CompanyName': field[1].css("a::text").get().split(" ")[-1],'UnifiedCreditCode': field[2].css("::text").get(),'Address': field[3].css("::text").get(),'EstablishmentNumber': field[4].css("a::text").get().split(" ")[-1],'EIAEngineersNumber': field[5].css("a::text").get().split(" ")[-1],'Status': field[6].get().split(" ")[-1].split("<")[0],'PunishmentDetail': field[7].css("a.amend-see::attr(href)").get().split("'")[-2],}

    {}中間構建了一個scrapy.Item對象,scrapy框架會將這個對象傳遞給pipelines.py進行下一步處理,如果沒有編寫pipelines.py,就是單純對item進行返回。
    這里我們通過yield返回了一個8個key的scrapy.Item對象。

    scrapy中的傳值的問題

    在scrapy中,callback同spider是在不同的進程中執行的,所以如果使用全局變量會遇到多進程讀寫的毛病。
    對于這一點,我們有兩種解決方案。

    從持久化數據源(數據庫/表格)中獲取數據

    這一塊的作法是根據url中的關鍵字進行解碼,采用解碼后的結果從持久化數據源中進行查表并獲取所需的關聯數據。

    def parse(self, response):punish_id = response.url.split("=")[-1]with open("./Requirement.csv") as csvfile:reader = csv.DictReader(csvfile)for row in reader:if row["PunishmentID"] == punish_id:unified_credit_code = row["UnifiedCreditCode"]company_code = row['技術單位名稱']

    上述例子是

  • 從url中解碼出punish_id
  • 將csv文件讀取為字典
  • 搜索csv文件中對應的域"PunishmentID",獲取相關的unified_credit_code和company_code
  • 使用cb_kwargs在request和callback回調函數之間進行傳參

    # 在Request發起端定義cb_kwargs,注意參數需要用dict來進行定義yield scrapy.Request(url=url, callback=self.parse2, cb_kwargs=dict(company_code=self.company_name, punish_id=self.punishment_number, unified_credit_code=self.unified_creditcode))#在callback函數中需要對應地聲明cb_kwargs的參數 def parse2(self, response, company_code, punish_id, unified_credit_code):

    這里,將全局變量self.company_name, self.punishment_number和self.unified_creditcode通過傳值的方式參數傳遞給回調函數,并確保了上述全局變量被改變后,不影響回調函數中對這些值的使用。

    注意:
    Request.cb_kwargs是在scrapy 1.7 版本后被引入的。之前的版本使用Request.meta給回調函數傳遞信息,但meta的下屬結構定義是固定的。1.7版本后,通常我們使用Request.cb_kwargs來處理用戶信息,而Request.meta作為中間件和擴展組件的通信使用。

    參考

    https://towardsdatascience.com/web-scraping-with-scrapy-theoretical-understanding-f8639a25d9cd
    https://docs.scrapy.org/en/latest/topics/request-response.html#topics-request-meta
    https://www.cnblogs.com/chenxi188/p/10848690.html

    總結

    以上是生活随笔為你收集整理的Scrapy中的yield使用的全部內容,希望文章能夠幫你解決所遇到的問題。

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