scrapy進階(豆瓣新書速遞)(比亞迪)

scrapy數據建模與請求

學習目標:

  1. 應用 在scrapy項目中進行建模
  2. 應用 構造Request對象,并發送請求
  3. 應用 利用meta參數在不同的解析函數中傳遞數據
  4. scrapy構造post請求

1. 數據建模

通常在做項目的過程中,在items.py中進行數據建模

1.1 為什么建模

  1. 定義item即提前規劃好哪些字段需要抓,防止手誤,因為定義好之后,在運行過程中,系統會自動檢查
  2. 配合注釋一起可以清晰的知道要抓取哪些字段,沒有定義的字段不能抓取,在目標字段少的時候可以使用字典代替

1.2 如何建模

在items.py文件中定義要提取的字段:

# Define here the models for your scraped items
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.htmlimport scrapy
class DoubanItem(scrapy.Item):# define the fields for your item here like:name = scrapy.Field()    # 名字content = scrapy.Field()  # 內容link = scrapy.Field()  # 鏈接txt = scrapy.Field()  #詳情介紹

1.3 如何使用模板類

模板類定義以后需要在爬蟲中導入并且實例化,之后的使用方法和使用字典相同

爬蟲文件.py

# -*- coding:utf-8 -*-
import scrapy
from douban.items import DoubanItem
....def parse(self, response):name = response.xpath('//h2[@class="clearfix"]/a/text()').extract()content = response.xpath('//p[@class="subject-abstract color-gray"]/text()').extract()link = response.xpath('//h2[@class="clearfix"]/a/@href').extract()for names, contents, links in zip(name, content, link):item = DoubanItem()  # 實例化后拿到模板類就可直接使用 本質是一個字典item['name'] = namesitem['content'] = contents.strip()item['link'] = links

注意:
1. from douban.items import DoubanItem這一行代碼中 注意item的正確導入路徑,忽略pycharm標記的錯誤
2. python中的導入路徑要訣:從哪里開始運行,就從哪里開始導入

1.4 開發流程總結

1. 創建項目scrapy startproject 項目名
2. 明確目標在items.py文件中進行建模  (一般來說在開發流程里建模是必須的,但如果字段特別少也可以選擇忽略)
3. 創建爬蟲3.1 創建爬蟲scrapy genspider 爬蟲名 允許的域3.2 完成爬蟲修改start_urls檢查修改allowed_domains在parse方法里編寫解析方法
4. 保存數據在pipelines.py文件中定義對數據處理的管道在settings.py文件中注冊啟用管道

2. 翻頁請求的思路

  1. 找到下一頁的url地址
  2. 把url地址構造成請求對象,傳遞給引擎

3. 構造Request對象,并發送請求

3.1 實現方法

  1. 確定url地址
  2. 構造請求,scrapy.Request(url,callback)
    • callback:指定響應體解析的函數名稱,表示該請求返回的響應使用哪一個函數進行解析(callback不賦值的話默認是給parse方法解析)
  3. 把請求交給引擎:yield scrapy.Request(url,callback)

3.2 豆瓣新書速遞爬蟲

通過爬取豆瓣新書速遞的頁面信息,學習如何實現翻頁請求

地址:豆瓣新書速遞

思路分析:
  1. 獲取首頁的響應數據(因為里面有我們想要的翻頁鏈接)
  2. 尋找下一頁的地址,進行翻頁,獲取數據
注意:
  1. 可以在settings中設置ROBOTS協議

    False表示忽略網站的robots.txt協議,默認為True

    ROBOTSTXT_OBEY = False

  2. 可以在settings中設置User-Agent:
    (scrapy發送的每一個請求的默認UA都是設置的這個User-Agent)

    USER_AGENT = ‘Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/59.0.3071.115 Safari/537.36’

3.3 代碼實現

在爬蟲文件的parse方法中:

....# 1,構造翻頁# 提取下一頁urlpart_url = response.xpath('//span[@class="next"]//a/@href').extract_first()# 2,判斷是否為下一頁的條件if '?subcat=' in part_url:# 構造完整的urlnext_url = response.urljoin(part_url)print("下一頁參數信息:", part_url)print("下一頁鏈接:", next_url)# 構造scrapy.Request對象,并yield給引擎,利用callback參數指定該Request對象之后獲取的響應用哪個函數進行解析 yield scrapy.Request(url=next_url, callback=self.parse)

3.4 scrapy.Request的更多參數

scrapy.Request(url[callback,method=“GET”,headers,body,cookies,meta,dont_filter=False])

參數解釋
  1. 中括號里的參數為可選參數
  2. callback:表示當前的url的響應交給哪個函數去處理
  3. meta:實現數據在不同的解析函數中傳遞,meta默認帶有部分數據,比如下載延遲,請求深度等
  4. dont_filter:默認為False,會過濾請求的url地址,即請求過的url地址不會繼續被請求,對需要重復請求的url地址可以把它設置為Ture,比如貼吧的翻頁請求,頁面的數據總是在變化;start_urls中的地址會被反復請求,否則程序不會啟動
  5. method:指定POST或GET請求
  6. headers:接收一個字典,其中不包括cookies
  7. cookies:接收一個字典,專門放置cookies
  8. body:接收json字符串,為POST的數據,發送payload_post請求時使用(在下面內容中會介紹post請求)

4. meta參數的使用

meta的作用:meta可以實現數據在不同的解析函數中的傳遞

使用場景:常用在數據分散在不同結構頁面中

在爬蟲文件的parse方法中,提取詳情頁增加之前callback指定的parse_detail函數:

# 爬蟲默認自帶的解析方法
def parse(self,response):yield scrapy.Request(url=item['link'],callback=self.parse_detail, meta={'item': item})# 新建一個解析方法 用于解析詳情頁 里面一定要有resposne參數
def parse_detail(self,response):# 獲取meta傳遞過來的參數給item字典接收item = resposne.meta["item"]
特別注意
  1. meta參數是一個字典
  2. meta字典中有一個固定的鍵proxy,表示代理ip,關于代理ip的使用我們將在scrapy的下載中間件進行介紹

scrapy中間件的使用

學習目標:

  1. 應用 scrapy中使用間件使用隨機UA的方法
  2. 應用 scrapy中使用代理ip的的方法

1.1 scrapy中間件的分類

根據scrapy運行流程中所在位置不同分為:

  1. 下載中間件
  2. 爬蟲中間件

scrapy默認情況下,兩中中間件都是在middlewares.py一個文件中,爬蟲中間件使用方法和下載中間件相同,且功能重復,通常使用下載中間件

1.2 scrapy中間件的作用:預處理request和response對象

  1. 對header以及cookie進行更換和處理
  2. 使用代理ip等
  3. 對請求進行定制化操作

2. 下載中間件的使用方法:

接下來我們對豆瓣爬蟲進行修改完善,通過下載中間件來學習如何使用中間件
編寫一個Downloader Middlewares和我們編寫一個pipeline一樣,定義一個類,然后在setting中開啟

Downloader Middlewares默認的方法:

  • process_request(self, request, spider):

    1. 當每個request通過下載中間件時,該方法被調用。
      2. 返回None值:沒有return也是返回None,該request對象傳遞給下載器,或通過引擎傳遞給其他權重低的process_request方法
      3. 返回Response對象:不再請求,把response返回給引擎
      4. 返回Request對象:把request對象通過引擎交給調度器,此時將不通過其他權重低的process_request方法
  • process_response(self, request, response, spider):

    1. 當下載器完成http請求,傳遞響應給引擎的時候調用
      2. 返回Resposne:通過引擎交給爬蟲處理或交給權重更低的其他下載中間件的process_response方法
      3. 返回Request對象:通過引擎交給調取器繼續請求,此時將不通過其他權重低的process_request方法
  • 在settings.py中配置開啟中間件,權重值越小越優先執行

3. 定義實現隨機User-Agent的下載中間件

3.1 在middlewares.py中完善代碼 middlewares.py中自帶的代碼可以刪除掉

import random
class UserAgentDownloadMiddleware(object):user_agent = ['Mozilla/5.0 (Windows NT 6.1; WOW64; rv:77.0) Gecko/20190101 Firefox/77.0','Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.77 Safari/537.36','Opera/9.80 (X11; Linux i686; Ubuntu/14.10) Presto/2.12.388 Version/12.16.2']# 方法名是scrapy規定的方法 (協商機制)# 每個交給下載器的request對象都會經過該方法,并期望返回responsedef process_request(self, request, spider):# 獲取隨機請求頭u_a = random.choice(self.user_agent)# 設置請求頭request.headers['User-Agent'] = u_a
3.2 在settings中設置開啟自定義的下載中間件,設置方法同管道

settings文件所寫參數的詳細說明可參考以下博客:

https://blog.csdn.net/Lan_cer/article/details/87554025

DOWNLOADER_MIDDLEWARES = {'douban.middlewares.UserAgentDownloadMiddleware': 200,
}

4. 代理ip的使用

4.1 思路分析

  1. 代理添加的位置:request.meta中增加proxy字段
  2. 獲取一個代理ip,賦值給request.meta['proxy']
    • 代理池中隨機選擇代理ip
    • 像代理ip的api發送請求獲取一個代理ip

4.2 具體實現

class RandomProxy(object):ip_list = ['116.26.39.23:4215','42.56.239.136:4278','115.234.192.226:4275',]def process_request(self, request, spider):proxy = random.choice(self.ip_list)# 需要加上https://,否則報錯# 修改請求的元數據字典  用于給框架中其他組件傳遞信息 比如給其添加一個代理request.meta['proxy'] = 'https://' + proxy
同理要在settings.py中開啟該中間件
DOWNLOADER_MIDDLEWARES = {'douban.middlewares.RandomProxy': 100,'douban.middlewares.UserAgentDownloadMiddleware': 200,
}

scrapy管道的使用

學習目標:

1. 掌握 scrapy管道(pipelines.py)的使用

之前我們在scrapy入門使用一節中學習了管道的基本使用,接下來我們深入的學習scrapy管道的使用
process_item(self,item,spider):

  • 管道類中必須有的函數
  • item指引擎傳過來的數據 實現對item數據的處理
  • 必須return item
  • spide指的是使用這個管道的爬蟲

2. 管道文件的修改

繼續完善豆瓣爬蟲,在pipelines.py代碼中完善

# -*- coding:utf-8 -*-
# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html# useful for handling different item types with a single interface
import json
import loggingfrom itemadapter import ItemAdapter
import pymysqlclass DoubanPipeline:def __init__(self):self.file = open('douban.json', 'a', encoding='utf-8')def process_item(self, item, spider):data = dict(item)json_data = json.dumps(data, ensure_ascii=False) + ',\n'self.file.write(json_data)# 不return的情況下,另一個權重較低的pipeline將不會獲得itemreturn item# 整個程序生命周期結束 內存銷毀 該方法才會執行結束def __del__(self):self.file.close()class DoubansqlPipeline:def __init__(self):# 連接數據庫                 用戶名       密碼             數據庫名               編碼self.db = pymysql.connect(user='root', password='admin', database='xiaoxiao', charset='utf8')self.cursor = self.db.cursor()  # 獲取操作游標def process_item(self, item, spider):# 此時item對象必須是一個字典,再插入,如果此時item是BaseItem則需要先轉換為字典:dict(BaseItem)item = dict(item)# print(item)try:sql = 'insert into db_data(name,content,link,txt) values(%s,%s,%s,%s)'  # SQL語句self.cursor.execute(sql, [item['name'], item['content'], item['link'], item['txt']])  # 執行sql語句self.db.commit()  # 提交except Exception as e:logging.error(f'數據存儲異常,原因:{e}')# 不return的情況下,另一個權重較低的pipeline將不會獲得itemreturn item# 當所屬類運行完成 這個方法就會關閉掉def close_spider(self, spider):self.db.close()

3. 開啟管道

在settings.py設置開啟pipeline:

ITEM_PIPELINES = {'douban.pipelines.DoubanPipeline': 300,   # 300表示權重'douban.pipelines.DoubansqlPipeline': 301,  # 權重值越小,越優先執行!
}

4. pipeline使用注意點

  1. 使用之前需要在settings中開啟
  2. pipeline在setting中鍵表示位置(即pipeline在項目中的位置可以自定義),值表示距離引擎的遠近,越近數據會越先經過:權重值小的優先執行
  3. 有多個pipeline的時候,process_item的方法必須return item,否則后一個pipeline取到的數據為None值
  4. pipeline中process_item的方法必須有,否則item沒有辦法接受和處理
  5. process_item方法接受item和spider,其中spider表示當前傳遞item過來的spider
  6. def init(self): (或者可以寫def open_spider(spider) 😃 都表示能夠在爬蟲開啟的時候執行一次
  7. def close_spider(self, spider): 能夠在爬蟲關閉的時候執行一次
  8. 上述倆個方法經常用于爬蟲和數據庫的交互,在爬蟲開啟的時候建立和數據庫的連接,在爬蟲關閉的時候斷開和數據庫的連接

小結

  • 管道能夠實現數據的清洗和保存,能夠定義多個管道實現不同的功能,其中有個三個方法
    • process_item(self,item,spider):實現對item數據的處理
    • open_spider(self, spider): 在爬蟲開啟的時候僅執行一次
    • close_spider(self, spider): 在爬蟲關閉的時候僅執行一次

scrapy.Request發送post請求

我們可以通過scrapy.Request()指定method、body參數來發送post請求;也可以使用scrapy.FormRequest()來發送post請求

1 發送post請求

注意:scrapy.FormRequest()能夠發送表單和ajax請求,參考閱讀 https://www.jb51.net/article/146769.htm

2 思路分析

  1. 找到post的url地址:然后定位url地址為https://www.bydauto.com.cn/api/comom/search_join_shop

  2. 找到請求體的規律:分析post請求的請求體(參數)

  3. start_urls中的url地址是交給parse處理的,如有必要,我們需要重寫start_request這個定制方法:
    爬蟲文件

import scrapy
import json
from jsonpath import jsonpathclass BydSpiderSpider(scrapy.Spider):name = 'byd_spider'# 1.檢查域名allowed_domains = ['bydauto.com']# 2.修改請求url# start_urls = ['https://www.bydauto.com.cn/api/comom/search_join_shop']# 注意post請求的起始url發請求的那一刻要求是str類型city_url = 'https://www.bydauto.com.cn/api/comom/search_join_shop'# post請求的參數payload = {"type": 2, "province": 430000, "city": 430100, "network": 'null'}# 3,構造起始方法:start_requests(self),此方法是spider模塊中的定制方法,是一個重寫方法,不能修改名字和參數# 作用:爬蟲從該方法開始,此時start_urls 和 parse( ) 函數可刪除,可在該start_requests函數中寫入多種請求def start_requests(self):# 4.將請求信息打包成一個請求對象 并將返回的響應數據交給parse方法處理yield scrapy.Request(url=self.city_url,method='POST',body=json.dumps(self.payload),callback=self.parse)# 5.解析比亞迪地址和電話信息def parse(self, response):json_data = response.json()address = jsonpath(json_data,'$..address')print(address)tel = jsonpath(json_data,'$..tel')print(tel)

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/13879.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/13879.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/13879.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

gt.qpa.xcb: could not connect to display : 1

報錯解釋: 這個錯誤通常發生在使用X11(X Window System)的Linux環境中,當嘗試啟動一個基于Qt平臺的應用程序時。錯誤信息表明程序無法連接到X服務器顯示設備,原因可能是沒有正確設置DISPLAY環境變量,或者用…

【Spring security】【pig】Note03-pig token令牌解析器過程

🌸🌸 pig token令牌解析器過程 🌸🌸 pig后端源碼 一、解析請求中的令牌值。 二、驗證令牌 內省并驗證給定的令牌,返回其屬性。返回映射表示令牌有效。 /*** author lengleng* date 2019/2/1 擴展用戶信息*/ publi…

Hot100-棧

20. 有效的括號 - 力扣&#xff08;LeetCode&#xff09; class Solution {public boolean isValid(String s) {//用map的鍵值對匹配左右括號//按照順序&#xff0c;先匹配的是左括號&#xff0c;所以棧里面放左括號HashMap<Character, Character> rlationship new Has…

deepinlinuxv23b3用lazarus3.2開發生成2維碼

下載&#xff1a; https://sourceforge.net/projects/lazarus/files/ 最新版3.2.2的fpc,3.2的lazarus sourceforge默認下載慢&#xff0c;選擇auto-select能夠選擇近的鏡像站點&#xff0c;還不行的話也能夠motrix下載會自動更換域名 linux的qrencode安裝是 sudo apt…

跨境小白shopee被封號的原因?如何有效預防?

提到跨境電商平臺&#xff0c;大家都知道亞馬遜、Temu、TikTok shop這些是比較大的電商平臺。但最近幾年&#xff0c;在東南亞市場上&#xff0c;Shopee蝦皮卻是頗負盛名的一個跨境電商平臺&#xff0c;這也讓眾多中國跨境小白蜂擁而至。目前shopee的商家正在不斷增多&#xff…

[力扣題解] 130. 被圍繞的區域

題目&#xff1a;130. 被圍繞的區域 思路 代碼 Method 1 : 深度優先搜索&#xff0c;自己寫的 class Solution { private:int dir[4][2] {{1, 0}, {-1, 0}, {0, 1}, {0, -1}};void dfs(vector<vector<char>>& board, vector<vector<bool>>&am…

vue3第三十四節(TS 之 interface 與 type 的異同)

1、interface 接口只能定義描述對象類型 如&#xff1a; interface PersonIn {name: string;age:number;job:string; }// 定義函數 interface FPerson {(a: number, b:string) > void }2、類型別名 type則可以定義多種類型 如&#xff1a; type userName string type…

DeepDriving | CUDA編程-02: 初識CUDA編程

本文來源公眾號“DeepDriving”&#xff0c;僅用于學術分享&#xff0c;侵權刪&#xff0c;干貨滿滿。 原文鏈接&#xff1a;CUDA編程-02&#xff1a; 初識CUDA編程 上一篇文章DeepDriving | CUDA編程-01&#xff1a; 搭建CUDA編程環境-CSDN博客介紹了如何搭建CUDA編程環境&a…

選擇、快排、堆排序、歸并

選擇排序 排序的核心是&#xff1a;在未排序的序列中&#xff0c;把未排序第一個元素和未排序的最小元素交換位置。 因此&#xff0c;設計時&#xff0c;顯然要設置兩重 for 循環 假設未排序的第一個元素稱為 a &#xff0c; 未排序的最小元素稱為 b 第一重 for 循環控制總…

web壓力測試,要不要過濾掉JS,CSS等請求?

在進行性能測試&#xff08;壓測&#xff09;時&#xff0c;是否過濾掉對JavaScript、CSS等靜態資源的請求&#xff0c;取決于你測試的目標和目的。 是測試服務端的性能還是前端的性能。這兩種目的所涉及到的測試場景和工具等方法是不一樣的。 一般的web產品&#xff0c;像cs…

java 8--Lambda表達式,Stream流

目錄 Lambda表達式 Lambda表達式的由來 Lambda表達式簡介 Lambda表達式的結構 Stream流 什么是Stream流&#xff1f; 什么是流呢&#xff1f; Stream流操作 中間操作 終端操作 Lambda表達式 Lambda表達式的由來 Java是面向對象語言&#xff0c;除了部分簡單數據類型…

利用kubeadm安裝k8s集群 以及跟harbor私有倉庫下載鏡像

目錄 環境準備 master&#xff08;2C/4G&#xff09; 192.168.88.3 docker、kubeadm、kubelet、kubectl、flannel node01&#xff08;2C/2G&#xff09; 192.168.88.4 docker、kubeadm、kubelet、kubectl、flannel node02&#xff08;…

2024中青杯數學建模競賽B題藥物屬性預測思路代碼論文分享

2024年中青杯數學建模競賽B題論文和代碼已完成&#xff0c;代碼為B題全部問題的代碼&#xff0c;論文包括摘要、問題重述、問題分析、模型假設、符號說明、模型的建立和求解&#xff08;問題1模型的建立和求解、問題2模型的建立和求解、問題3模型的建立和求解&#xff09;、模型…

QT調用Tinyxml2庫解析XML結構文件

在學習SVG結構的時候&#xff0c;發現SVG結構可以通過以XML文件直接解析&#xff0c;所以就去了解了Tinyxml2庫的使用&#xff0c;相關教程也比較多。 個人感覺Tinyxml2庫比官方的XML解析庫更好用&#xff0c;這里做個技術總結&#xff0c;記錄Tinyxml2庫解析XML文件結構的簡單…

【Linux取經路】一個簡單的日志模塊

文章目錄 一、可變參數的使用二、Log2.1 日志打印2.1.1 時間獲取2.1.2 日志分塊打印 2.2 打印模式選擇2.3 Log 使用樣例2.4 Log 完整源碼 三、結語 一、可變參數的使用 int sum(int n, ...) {va_list s; // va_list 本質上就是一個指針va_start(s, n); int sum 0;while(n){su…

為什么以太網適配器不是192.168而是196.254【筆記】

為什么以太網適配器不是192.168而是196.254【筆記】 前言版權為什么以太網適配器不是192.168而是196.254最后 前言 2024-03-12 22:55:34 公開發布于 2024-5-22 00:20:35 以下內容源自《【筆記】》 僅供學習交流使用 版權 禁止其他平臺發布時刪除以下此話 本文首次發布于CS…

Linux: tools: crash: not a supported file format

這個原因是,通過比對每個format的magic數值,或者其他的信息,來看是否屬于某個format,如果都不符合,就會出現這個錯誤。說明kernel的coredump文件,dump的有些問題。 main (argc=3, argv=0x7fffffffda88) at main.c:496 496 } else if (is_compressed…

Java高級面試精粹:問題與解答集錦(一)

Java 面試問題及答案 1. 什么是Java中的多態&#xff0c;它是如何實現的&#xff1f; 答案&#xff1a; 多態是Java中的一個核心概念&#xff0c;它允許不同類的對象對同一消息做出響應&#xff0c;但具體的行為會根據對象的實際類型而有所不同。多態主要通過以下兩種方式實現…

git命令行指引

命令行指引 您還可以按照以下說明從計算機中上傳現有文件。 Git 全局設置 git config --global user.name "lizhijun" git config --global user.email "oldgunqfhotmail.com"創建一個新倉庫 git clone gitfiles.tfedu.net:aigk985-gaokao/Folder-watc…

計算機畢業設計 | node.js(Express)+vue影院售票商城 電影放映購物系統(附源碼+論文)

1&#xff0c;緒論 1.1 項目背景 最近幾年&#xff0c;我國影院企業發展迅猛&#xff0c;各大電影院不斷建設新的院線&#xff0c;每年新投入使用的熒幕數目逐年顯著上升。這離不開人們的觀影需求及對觀影的過程要求的不斷進步。廣大觀影消費者需要知道自己的空閑時間&#x…