柚子快報邀請碼778899分享:pyhton-8-scrapy
柚子快報邀請碼778899分享:pyhton-8-scrapy
scrapy
scrapy安裝scrapy項目的創(chuàng)建以及運行scrapy架構(gòu)組成scrapy工作原理scrapy shellyieldMysqlpymysql的使用步驟CrawlSpider
scrapy安裝
點我學(xué)習(xí)scrapy的安裝
1. scrapy是什么?
Scrapy是一個為了爬取網(wǎng)站數(shù)據(jù),提取結(jié)構(gòu)性數(shù)據(jù)而編寫的應(yīng)用框架。 可以應(yīng)用在包括數(shù)據(jù)挖掘,信息處理或存儲歷史數(shù)據(jù)等一系列的程序中。
2. 安裝scrapy:
pip install scrapy
安裝過程中出錯:
如果安裝有錯誤?。。。?/p>
pip install Scrapy
building 'twisted.test.raiser' extension
error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++
Build Tools": http://landinghub.visualstudio.com/visual‐cpp‐build‐tools
解決方案:
http://www.lfd.uci.edu/~gohlke/pythonlibs/#twisted
下載twisted對應(yīng)版本的whl文件(如我的Twisted‐17.5.0‐cp36‐cp36m‐win_amd64.whl),cp后面是
python版本,amd64代表64位,運行命令:
pip install C:\Users\...\Twisted‐17.5.0‐cp36‐cp36m‐win_amd64.whl
pip install Scrapy
如果再報錯
python ‐m pip install ‐‐upgrade pip
如果再報錯 win32
解決方法:
pip install pypiwin32
再報錯:使用anaconda
使用步驟:
打開anaconda
點擊environments
點擊not installed
輸入scrapy
apply
在pycharm中選擇anaconda的環(huán)境
scrapy項目的創(chuàng)建以及運行
3. 創(chuàng)建scrapy項目:
終端輸入 scrapy startproject 項目名稱
注意:
項目的名字不允許使用數(shù)字開頭 也不能包含中文要在spiders文件夾中創(chuàng)建爬蟲文件cd 項目的名字\項目的名字\spiders
創(chuàng)建爬蟲文件
scrapy genspier 爬蟲的文件名 要爬取的網(wǎng)頁
eg: scrapy genspider baidu http://baidu.com
運行爬蟲代碼
scrapy crawl 爬蟲的名字
eg:
scrapy crawl baidu
在運行前我們需要把setting中的君子協(xié)議給注釋掉,如下圖
這是各個瀏覽器之間的協(xié)議,我們不需要遵守 我們將紅圈中的內(nèi)容將其注釋掉
import scrapy
class BaiduSpider(scrapy.Spider):
#爬蟲的名字,運行爬蟲的時候 使用的值
name = "baidu"
#允許訪問的域名
allowed_domains = ["www.baidu.com"]
#起始的url地址 指的是第一次訪問的域名
#start_urls是在allowed_domains前面添加http://
start_urls = ["http://www.baidu.com"]
#是執(zhí)行了start_urls之后 執(zhí)行的方法 方法中的response 就是返回的那個對象
#相當(dāng)于 response=urllib.request.urlopen()
# response=request.get()
def parse(self, response):
print('這是一個測試')
4. 項目組成:
scrapy項目的結(jié)構(gòu)
項目名字
項目名字
spiders
__init__.py
自定義的爬蟲文件.py ‐‐‐》由我們自己創(chuàng)建,是實現(xiàn)爬蟲核心功能的文件
__init__.py
items.py ‐‐‐》定義數(shù)據(jù)結(jié)構(gòu)的地方,是一個繼承自scrapy.Item的類
middlewares.py ‐‐‐》中間件 代理
pipelines.py ‐‐‐》管道文件,里面只有一個類,用于處理下載數(shù)據(jù)的后續(xù)處理
默認(rèn)是300優(yōu)先級,值越小優(yōu)先級越高(1‐1000)
settings.py ‐‐‐》配置文件 比如:是否遵守robots協(xié)議,User‐Agent定義等
我們以58同城的網(wǎng)頁為例,我們創(chuàng)建一個scrapy文件
6. 創(chuàng)建爬蟲文件:
(1)跳轉(zhuǎn)到spiders文件夾 cd 目錄名字/目錄名字/spiders
(2)scrapy genspider 爬蟲名字 網(wǎng)頁的域名
爬蟲文件的基本組成:
繼承scrapy.Spider類
name = 'baidu' ‐‐‐》 運行爬蟲文件時使用的名字
allowed_domains ‐‐‐》 爬蟲允許的域名,在爬取的時候,如果不是此域名之下的
url,會被過濾掉
start_urls ‐‐‐》 聲明了爬蟲的起始地址,可以寫多個url,一般是一個
parse(self, response) ‐‐‐》解析數(shù)據(jù)的回調(diào)函數(shù)
response.text ‐‐‐》響應(yīng)的是字符串
response.body ‐‐‐》響應(yīng)的是二進(jìn)制文件
response.xpath()‐》xpath方法的返回值類型是selector列表
extract() ‐‐‐》提取的是selector對象的是data
extract_first() ‐‐‐》提取的是selector列表中的第一個數(shù)據(jù)
import scrapy
class TcSpider(scrapy.Spider):
name = "tc"
allowed_domains = ["hezhou.58.com"]
start_urls = ["https://hezhou.58.com/sou/?key=%E5%89%8D%E7%AB%AF%E5%BC%80%E5%8F%91&classpolicy=classify_B%2Cuuid_BWFczZwN8WKQ2ENkAYcww7TidZFSpKTz&search_uuid=BWFczZwN8WKQ2ENkAYcww7TidZFSpKTz&search_type=input"]
def parse(self, response):
content=response.text
span=response.xpath('//div[@id="filter"]/div[@class="tabs"]/a/span')[0]
print('=======')
print(span.extract())
7.運行爬蟲文件:
scrapy crawl 爬蟲名稱
注意:應(yīng)在spiders文件夾內(nèi)執(zhí)行
scrapy架構(gòu)組成
1.(1)引擎 ‐‐‐》自動運行,無需關(guān)注,會自動組織所有的請求對象,分發(fā)給下載器
(2)下載器 ‐‐‐》從引擎處獲取到請求對象后,請求數(shù)據(jù)
(3)spiders ‐‐‐》Spider類定義了如何爬取某個(或某些)網(wǎng)站。包括了爬取的動作(例
如:是否跟進(jìn)鏈接)以及如何從網(wǎng)頁的內(nèi)容中提取結(jié)構(gòu)化數(shù)據(jù)(爬取item)。 換句話說,Spider就是您定義爬取的動作及
分析某個網(wǎng)頁(或者是有些網(wǎng)頁)的地方。
(4)調(diào)度器 ‐‐‐》有自己的調(diào)度規(guī)則,無需關(guān)注
(5)管道(Item pipeline) ‐‐‐》最終處理數(shù)據(jù)的管道,會預(yù)留接口供我們處理數(shù)據(jù)
當(dāng)Item在Spider中被收集之后,它將會被傳遞到Item Pipeline,一些組件會按照一定的順序執(zhí)行對Item的處理。
每個item pipeline組件(有時稱之為“Item Pipeline”)是實現(xiàn)了簡單方法的Python類。他們接收到Item并通過它執(zhí)行
一些行為,同時也決定此Item是否繼續(xù)通過pipeline,或是被丟棄而不再進(jìn)行處理。
以下是item pipeline的一些典型應(yīng)用:
1. 清理HTML數(shù)據(jù)
2. 驗證爬取的數(shù)據(jù)(檢查item包含某些字段)
3. 查重(并丟棄)
4. 將爬取結(jié)果保存到數(shù)據(jù)庫
scrapy工作原理
scrapy shell
1.什么是scrapy shell?
Scrapy終端,是一個交互終端,供您在未啟動spider的情況下嘗試及調(diào)試您的爬取代碼。 其本意是用來測試提取
數(shù)據(jù)的代碼,不過您可以將其作為正常的Python終端,在上面測試任何的Python代碼。
該終端是用來測試XPath或CSS表達(dá)式,查看他們的工作方式及從爬取的網(wǎng)頁中提取的數(shù)據(jù)。 在編寫您的spider時,該
終端提供了交互性測試您的表達(dá)式代碼的功能,免去了每次修改后運行spider的麻煩。
一旦熟悉了Scrapy終端后,您會發(fā)現(xiàn)其在開發(fā)和調(diào)試spider時發(fā)揮的巨大作用。
2.安裝ipython
安裝:pip install ipython
簡介:如果您安裝了 IPython ,Scrapy終端將使用 IPython (替代標(biāo)準(zhǔn)Python終端)。 IPython 終端與其他相
比更為強(qiáng)大,提供智能的自動補(bǔ)全,高亮輸出,及其他特性。
3.應(yīng)用:(1)scrapy shell www.baidu.com
(2)scrapy shell http://www.baidu.com
(3) scrapy shell "http://www.baidu.com"
(4) scrapy shell "www.baidu.com"
語法:
(1)response對象:
response.body
response.text
response.url
response.status
(2)response的解析:
response.xpath() (常用)
使用xpath路徑查詢特定元素,返回一個selector列表對象
response.css()
使用css_selector查詢元素,返回一個selector列表對象
獲取內(nèi)容 :response.css('#su::text').extract_first()
獲取屬性 :response.css('#su::attr(“value”)').extract_first()
(3)selector對象(通過xpath方法調(diào)用返回的是seletor列表)
extract()
提取selector對象的值
如果提取不到值 那么會報錯
使用xpath請求到的對象是一個selector對象,需要進(jìn)一步使用extract()方法拆
包,轉(zhuǎn)換為unicode字符串
extract_first()
提取seletor列表中的第一個值
如果提取不到值 會返回一個空值
返回第一個解析到的值,如果列表為空,此種方法也不會報錯,會返回一個空值
xpath()
css()
注意:每一個selector對象可以再次的去使用xpath或者css方法
進(jìn)入到scrapy shell的終端 直接在window的終端中輸入scrapy shell 域名如果想看到一些高亮 或者 自動補(bǔ)全 那么可以安裝ipython pip install ipython
yield
1. 帶有 yield 的函數(shù)不再是一個普通函數(shù),而是一個生成器generator,可用于迭代
2. yield 是一個類似 return 的關(guān)鍵字,迭代一次遇到y(tǒng)ield時就返回yield后面(右邊)的值。重點是:下一次迭代
時,從上一次迭代遇到的yield后面的代碼(下一行)開始執(zhí)行
3. 簡要理解:yield就是 return 返回一個值,并且記住這個返回的位置,下次迭代就從這個位置后(下一行)開始
案例:
1.當(dāng)當(dāng)網(wǎng) (1)yield(2).管道封裝(3).多條管道下載 (4)多頁數(shù)據(jù)下載
2.電影天堂 (1)一個item包含多級頁面的數(shù)據(jù)
我們通過當(dāng)當(dāng)圖書網(wǎng),爬取了圖書的圖片,名字和價格,在爬取圖片時需要注意的是網(wǎng)站的圖片會進(jìn)行懶加載,同時我們爬取的第一個圖片為none,這時候我們就需要使用結(jié)構(gòu)控制語句
import scrapy
class DangSpider(scrapy.Spider):
name = "dang"
allowed_domains = ["category.dangdang.com"]
start_urls = ["https://category.dangdang.com/cp01.01.02.00.00.00.html"]
def parse(self, response):
# src=//ul[@id="component_59"]/li/a/img/@src
# alt=//ul[@id="component_59"]/li/a/img/@alt
# price=//ul[@id="component_59"]/li/p[@class="price"]/span[1]/text()
li_list=response.xpath('//ul[@id="component_59"]/li')
for li in li_list:
src = li.xpath('.//img/@data-original').extract_first()
# 第一張圖片和其他的圖片的標(biāo)簽的屬性是不一樣的
# 第一張圖片的src是可以使用的 其他的圖片的地址是data-original
if src:
src = src
else:
src = li.xpath('.//img/@src').extract_first()
name = li.xpath('.//img/@alt').extract_first()
price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
print(src,name,price)
我們在items.py中定義數(shù)據(jù)結(jié)構(gòu),你需要什么結(jié)構(gòu)就定義什么結(jié)構(gòu)
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class ScrapyDangdang095Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
# 圖片
src=scrapy.Field()
#名字
name=scrapy.Field()
#價格
price=scrapy.Field()
我們需要使用這個數(shù)據(jù)結(jié)構(gòu)就需要先導(dǎo)入這個數(shù)據(jù)結(jié)構(gòu)
#導(dǎo)入
from scrapy_dangdang_095.items import ScrapyDangdang095Item
我們還需要將該數(shù)據(jù)導(dǎo)入數(shù)據(jù)結(jié)構(gòu)中
book=ScrapyDangdang095Item(src=src,name=name,price=price)
我們使用yield進(jìn)行數(shù)據(jù)的下載
1. 帶有 yield 的函數(shù)不再是一個普通函數(shù),而是一個生成器generator,可用于迭代
2. yield 是一個類似 return 的關(guān)鍵字,迭代一次遇到y(tǒng)ield時就返回yield后面(右邊)的值。重點是:下一次迭代
時,從上一次迭代遇到的yield后面的代碼(下一行)開始執(zhí)行
3. 簡要理解:yield就是 return 返回一個值,并且記住這個返回的位置,下次迭代就從這個位置后(下一行)開始
如果想使用管道的話,我們就必須在setting中開啟管道 我們在setting中將下圖的注釋解開 需要注意的是管道可以有很多個,那么管道是有優(yōu)先級的,優(yōu)先級的范圍是1到1000 值越小優(yōu)先級越高 管道代碼
# 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
from itemadapter import ItemAdapter
# 如果想使用管道的話 那么就必須在settings中開啟管道
class ScrapyDangdang095Pipeline:
# 在爬蟲文件開始的之前就執(zhí)行的一個方法
def open_spider(self,spider):
self.fp = open('book.json','w',encoding='utf-8')
# item就是yield后面的book對象
def process_item(self, item, spider):
# 以下這種模式不推薦 因為每傳遞過來一個對象 那么就打開一次文件 對文件的操作過于頻繁
# # (1) write方法必須要寫一個字符串 而不能是其他的對象
# # (2) w模式 會每一個對象都打開一次文件 覆蓋之前的內(nèi)容
# with open('book.json','a',encoding='utf-8')as fp:
# fp.write(str(item))
self.fp.write(str(item))
return item
解決對文件的打開和關(guān)閉過于頻繁
# 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
from itemadapter import ItemAdapter
# 如果想使用管道的話 那么就必須在settings中開啟管道
class ScrapyDangdang095Pipeline:
# 在爬蟲文件開始的之前就執(zhí)行的一個方法
def open_spider(self,spider):
self.fp = open('book.json','w',encoding='utf-8')
# item就是yield后面的book對象
def process_item(self, item, spider):
# 以下這種模式不推薦 因為每傳遞過來一個對象 那么就打開一次文件 對文件的操作過于頻繁
# # (1) write方法必須要寫一個字符串 而不能是其他的對象
# # (2) w模式 會每一個對象都打開一次文件 覆蓋之前的內(nèi)容
# with open('book.json','a',encoding='utf-8')as fp:
# fp.write(str(item))
self.fp.write(str(item))
return item
# 在爬蟲文件執(zhí)行完之后 執(zhí)行的方法
def close_spider(self,spider):
self.fp.close()
開啟多條管道下載
class 自定義:
def process_item(self,item,spider):
return intem
我們自定義為DangDangDownloadPipeline 我們需要在setting中開啟管道
'scrapy_dangdang_095.pipelines.DangDangDownloadPipeline':301
我們創(chuàng)建一個books文件夾用來接收我們爬取的的圖片 pipelines.py中的代碼如下
# 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
from itemadapter import ItemAdapter
# 如果想使用管道的話 那么就必須在settings中開啟管道
class ScrapyDangdang095Pipeline:
# 在爬蟲文件開始的之前就執(zhí)行的一個方法
def open_spider(self,spider):
self.fp = open('book.json','w',encoding='utf-8')
# item就是yield后面的book對象
def process_item(self, item, spider):
# 以下這種模式不推薦 因為每傳遞過來一個對象 那么就打開一次文件 對文件的操作過于頻繁
# # (1) write方法必須要寫一個字符串 而不能是其他的對象
# # (2) w模式 會每一個對象都打開一次文件 覆蓋之前的內(nèi)容
# with open('book.json','a',encoding='utf-8')as fp:
# fp.write(str(item))
self.fp.write(str(item))
return item
# 在爬蟲文件執(zhí)行完之后 執(zhí)行的方法
def close_spider(self,spider):
self.fp.close()
import urllib.request
# 多條管道開啟
# (1) 定義管道類
# (2) 在settings中開啟管道
# 'scrapy_dangdang_095.pipelines.DangDangDownloadPipeline':301
class DangDangDownloadPipeline:
def process_item(self, item, spider):
url = 'http:' + item.get('src')#注意src前面沒有http,我們需要自行添加
filename = './books/' + item.get('name') + '.jpg'
urllib.request.urlretrieve(url = url, filename= filename)
return item
接下來哦我們就可以進(jìn)階到多頁面的下載。 我們獲取每一頁的請求url尋找規(guī)律
# http://category.dangdang.com/pg3-cp01.01.02.00.00.00.html
# http://category.dangdang.com/pg4-cp01.01.02.00.00.00.html
我們發(fā)現(xiàn)只有在pg 后面的數(shù)字是不同的,我們將其進(jìn)行初始化,將數(shù)字之前的網(wǎng)址和數(shù)字之后的網(wǎng)址進(jìn)行字符串拼接
#初始化
base_url = 'http://category.dangdang.com/pg'
page = 1
if self.page < 100:
self.page = self.page + 1
url = self.base_url + str(self.page) + '-cp01.01.02.00.00.00.html'
# 怎么去調(diào)用parse方法
# scrapy.Request就是scrpay的get請求
# url就是請求地址
# callback是你要執(zhí)行的那個函數(shù) 注意不需要加()
yield scrapy.Request(url=url,callback=self.parse)
在這段代碼中,回調(diào)函數(shù)是 parse 方法。在 Scrapy 中,回調(diào)函數(shù)指的是在請求完成后執(zhí)行的函數(shù),用于
處理響應(yīng)的數(shù)據(jù)。
在這個例子中,當(dāng)爬蟲發(fā)起請求后,當(dāng)響應(yīng)返回時,Scrapy 將調(diào)用 parse 方法來處理響應(yīng)的數(shù)據(jù)。
在 yield scrapy.Request(url=url, callback=self.parse) 這行代碼中,callback=self.parse 指定了當(dāng)請求
完成后要執(zhí)行的回調(diào)函數(shù),即 parse 方法。
在 Python 中,self 是一個慣例,用于引用類實例中的屬性和方法。在類定義中,self 是第一個參數(shù),用于指代類的實例本身。在類的方法內(nèi)部,通過 self 可以訪問該類的屬性和方法。
在這個例子中,self.page 是指該類的一個屬性,而不是一個局部變量。通過在 self 前面加上 self,可以確保在類的其他方法中也可以訪問和修改這個屬性。
如果在方法中直接使用 page,Python 會認(rèn)為它是一個局部變量,而不是類的屬性。為了在整個類中共享和訪問 page 屬性,需要使用 self.page 來明確地指示這是類的屬性。
完整代碼如下
import scrapy
from scrapy_dangdang_095.items import ScrapyDangdang095Item
class DangSpider(scrapy.Spider):
name = 'dang'
# 如果是多頁下載的話 那么必須要調(diào)整的是allowed_domains的范圍 一般情況下只寫域名
allowed_domains = ['category.dangdang.com']
start_urls = ['http://category.dangdang.com/cp01.01.02.00.00.00.html']
base_url = 'http://category.dangdang.com/pg'
page = 1
def parse(self, response):
# pipelines 下載數(shù)據(jù)
# items 定義數(shù)據(jù)結(jié)構(gòu)的
# src = //ul[@id="component_59"]/li//img/@src
# alt = //ul[@id="component_59"]/li//img/@alt
# price = //ul[@id="component_59"]/li//p[@class="price"]/span[1]/text()
# 所有的seletor的對象 都可以再次調(diào)用xpath方法
li_list = response.xpath('//ul[@id="component_59"]/li')
for li in li_list:
src = li.xpath('.//img/@data-original').extract_first()
# 第一張圖片和其他的圖片的標(biāo)簽的屬性是不一樣的
# 第一張圖片的src是可以使用的 其他的圖片的地址是data-original
if src:
src = src
else:
src = li.xpath('.//img/@src').extract_first()
name = li.xpath('.//img/@alt').extract_first()
price = li.xpath('.//p[@class="price"]/span[1]/text()').extract_first()
book = ScrapyDangdang095Item(src=src,name=name,price=price)
# 獲取一個book就將book交給pipelines
yield book
# 每一頁的爬取的業(yè)務(wù)邏輯全都是一樣的,所以我們只需要將執(zhí)行的那個頁的請求再次調(diào)用parse方法
# 就可以了
# http://category.dangdang.com/pg2-cp01.01.02.00.00.00.html
# http://category.dangdang.com/pg3-cp01.01.02.00.00.00.html
# http://category.dangdang.com/pg4-cp01.01.02.00.00.00.html
if self.page < 100:
self.page = self.page + 1
url = self.base_url + str(self.page) + '-cp01.01.02.00.00.00.html'
# 怎么去調(diào)用parse方法
# scrapy.Request就是scrpay的get請求
# url就是請求地址
# callback是你要執(zhí)行的那個函數(shù) 注意不需要加()
yield scrapy.Request(url=url,callback=self.parse)
接下來我們以電影天堂為例 我們獲取網(wǎng)頁的請求頭網(wǎng)址
我們創(chuàng)建好目錄和爬蟲文件
我們先測試看看網(wǎng)址做了什么反爬 網(wǎng)址并沒有做反爬 接下來我們的需求是獲取電影的名字和圖片 我們現(xiàn)在items.py中定義好數(shù)據(jù)結(jié)構(gòu)
# Define here the models for your scraped items
#
# See documentation in:
# https://docs.scrapy.org/en/latest/topics/items.html
import scrapy
class ScrapyMovie099Item(scrapy.Item):
# define the fields for your item here like:
# name = scrapy.Field()
name = scrapy.Field()
src = scrapy.Field()
我們獲取名字和圖片,使用的xpath語句表達(dá),因為圖片在鏈接中,則我們使用xpath語句表達(dá)出這個鏈接
a_list=response.xpath('//div[@class="co_content8"]//td[2]//a[2]')
for a in a_list:
name=a.xpath('./text(').extract_first()
href=a.xpath('./@href').extract_first()
我們要獲取圖片對第二頁的鏈接進(jìn)行訪問,我們自定義一個第二頁的鏈接的函數(shù),需要注意的是我們要注意 allowed_domains允許訪問的域名的范圍
# 對第二頁的鏈接發(fā)起訪問
yield scrapy.Request(url=url, callback=self.parse_second, meta={'name': name})
這段代碼使用了 Scrapy 的異步請求機(jī)制,通過 `yield` 關(guān)鍵字創(chuàng)建了一個 `scrapy.Request` 對象,用于發(fā)起對第二頁的請求。
讓我們逐一解釋這段代碼的各個部分:
- `yield`: 在 Python 中,`yield` 關(guān)鍵字用于生成器函數(shù)中,表示將結(jié)果產(chǎn)生給調(diào)用者,并暫停執(zhí)行當(dāng)前函數(shù)。在 Scrapy 中,使用 `yield` 關(guān)鍵字可以將請求、數(shù)據(jù)等生成為 Scrapy 框架可以處理的對象,從而實現(xiàn)異步處理和高效的爬取。
- `scrapy.Request`: 這是 Scrapy 框架中用于發(fā)起 HTTP 請求的類。它接受多個參數(shù),其中 `url` 參數(shù)是要請求的 URL,`callback` 參數(shù)是指定請求成功后的回調(diào)函數(shù),`meta` 參數(shù)是一個字典,用于傳遞額外的數(shù)據(jù)。
- `url=url`: 這是請求的 URL,即第二頁電影信息的鏈接。在原代碼中,它是通過將第一頁提取的相對鏈接拼接而成的絕對鏈接。
- `callback=self.parse_second`: 這是請求成功后的回調(diào)函數(shù)。在原代碼中,它指定為 `parse_second`,即第二頁響應(yīng)成功后會調(diào)用 `parse_second` 方法來處理響應(yīng)。
- `meta={'name': name}`: 這是一個字典,用于傳遞額外的數(shù)據(jù)。在原代碼中,它將電影的名稱傳遞給了第二頁請求,這樣在第二頁的解析函數(shù)中可以使用這個名稱來進(jìn)一步處理電影信息。
總的來說,這段代碼的作用是發(fā)起一個對第二頁的異步請求,并在請求成功后調(diào)用 `parse_second` 方法來處理第二頁的響應(yīng)。同時,通過 `meta` 參數(shù)將電影名稱傳遞給了第二頁的解析函數(shù)。
第二個函數(shù)代碼如下
def parse_second(self, response):
# 注意 如果拿不到數(shù)據(jù)的情況下 一定檢查你的xpath語法是否正確
src = response.xpath('//div[@id="Zoom"]//img/@src').extract_first()
# 接受到請求的那個meta參數(shù)的值
name = response.meta['name']
movie = ScrapyMovie099Item(src=src, name=name)
yield movie
完整代碼如下
import scrapy
from scrapy_099_mv.items import ScrapyMovie099Item
class MvSpider(scrapy.Spider):
name = "mv"
allowed_domains = ["www.dygod.net"]
start_urls = ["https://www.dygod.net/html/gndy/china/index.html"]
def parse(self, response):
a_list = response.xpath('//div[@class="co_content8"]//td[2]//a[2]')
for a in a_list:
# 獲取第一頁的name 和 要點擊的鏈接
name = a.xpath('./text()').extract_first()
href = a.xpath('./@href').extract_first()
# 第二頁的地址是
url = 'https://www.dygod.net/' + href
print(url)
# 對第二頁的鏈接發(fā)起訪問
yield scrapy.Request(url=url, callback=self.parse_second, meta={'name': name})
def parse_second(self, response):
# 注意 如果拿不到數(shù)據(jù)的情況下 一定檢查你的xpath語法是否正確
src = response.xpath('//div[@id="Zoom"]//img/@src').extract_first()
# 接受到請求的那個meta參數(shù)的值
name = response.meta['name']
movie = ScrapyMovie099Item(src=src, name=name)#使用from引入的數(shù)據(jù)結(jié)構(gòu)
yield movie#將movie返回給管道,我們需要將管道打開
pipelines.py的代碼如下
# 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
from itemadapter import ItemAdapter
class ScrapyMovie099Pipeline:
def open_spider(self,spider):
self.fp = open('movie.json','w',encoding='utf-8')
def process_item(self, item, spider):
self.fp.write(str(item))
return item
def close_spider(self,spider):
self.fp.close()
這幾個函數(shù)是定義在 Scrapy 的 Item Pipeline 中的方法,用于對爬取到的數(shù)據(jù)進(jìn)行處理和存儲。下面是每個方法的作用:
1. `open_spider(self, spider)`: 這個方法在爬蟲被打開時調(diào)用,用于執(zhí)行一些初始化操作。在這個例子中,`open_spider` 方法打開了一個名為 `movie.json` 的文件,用于將處理后的數(shù)據(jù)寫入到這個文件中。具體操作是使用 `open` 函數(shù)打開一個文件對象 `self.fp`,該文件對象用于寫入數(shù)據(jù),并指定編碼格式為 `utf-8`。
2. `process_item(self, item, spider)`: 這個方法是用來處理每個從爬蟲中得到的 item 的。在這里,方法將每個 item 轉(zhuǎn)換為字符串形式,并將其寫入到之前創(chuàng)建的文件對象 `self.fp` 中。最后,該方法返回處理后的 item。
3. `close_spider(self, spider)`: 這個方法在爬蟲被關(guān)閉時調(diào)用,用于執(zhí)行一些清理操作。在這個例子中,`close_spider` 方法關(guān)閉了之前打開的文件對象 `self.fp`,確保文件處理的完成和資源的釋放。通過調(diào)用 `close` 方法,將文件對象 `self.fp` 關(guān)閉,以便文件被正確地保存和釋放資源。
綜合來看,這幾個函數(shù)構(gòu)成了一個簡單的 Item Pipeline,用于將爬取到的數(shù)據(jù)存儲到名為 `movie.json` 的文件中。具體操作是在 `open_spider` 方法中打開文件,然后在 `process_item` 方法中將每個 item 寫入文件,最后在 `close_spider` 方法中關(guān)閉文件。這種設(shè)計模式可以保證數(shù)據(jù)的正確存儲和資源的正確釋放。
Mysql
(1)下載(https://dev.mysql.com/downloads/windows/installer/5.7.html) (2)安裝(https://jingyan.baidu.com/album/d7130635f1c77d13fdf475df.html)
pymysql的使用步驟
1.pip install pymysql
2.pymysql.connect(host,port,user,password,db,charset)
3.conn.cursor()
4.cursor.execute()
CrawlSpider
1.繼承自scrapy.Spider
2.獨門秘笈
CrawlSpider可以定義規(guī)則,再解析html內(nèi)容的時候,可以根據(jù)鏈接規(guī)則提取出指定的鏈接,然后再向這些鏈接發(fā)
送請求
所以,如果有需要跟進(jìn)鏈接的需求,意思就是爬取了網(wǎng)頁之后,需要提取鏈接再次爬取,使用CrawlSpider是非常
合適的
3.提取鏈接
鏈接提取器,在這里就可以寫規(guī)則提取指定鏈接
scrapy.linkextractors.LinkExtractor(
allow = (), # 正則表達(dá)式 提取符合正則的鏈接
deny = (), # (不用)正則表達(dá)式 不提取符合正則的鏈接
allow_domains = (), # (不用)允許的域名
deny_domains = (), # (不用)不允許的域名
restrict_xpaths = (), # xpath,提取符合xpath規(guī)則的鏈接
restrict_css = () # 提取符合選擇器規(guī)則的鏈接)
4.模擬使用
正則用法:links1 = LinkExtractor(allow=r'list_23_\d+\.html')
xpath用法:links2 = LinkExtractor(restrict_xpaths=r'//div[@class="x"]')
css用法:links3 = LinkExtractor(restrict_css='.x')
5.提取連接
link.extract_links(response)
使用演示
打開scrapy shell 網(wǎng)址
提取鏈接提取器可以提取當(dāng)前頁面中所有符合規(guī)則的鏈接
from scrapy.linkextractors import LinkExtractor
#正則表達(dá)式
# \d:表示數(shù)字 +表示1到多個數(shù)字
link = LinkExtractor(allow=r'/play/4483-1-\d+\.html')
#輸出
link.extract_linke(response)
#xpath方式
link1 = LinkExtractor(restrict_xpaths="http://div[@class='module-play-list']/div/a/@href")
#輸出
link.extract_linke(response)
6.注意事項
【注1】callback只能寫函數(shù)名字符串, callback='parse_item'
【注2】在基本的spider中,如果重新發(fā)送請求,那里的callback寫的是 callback=self.parse_item 【注‐
‐稍后看】follow=true 是否跟進(jìn) 就是按照提取連接規(guī)則進(jìn)行提取
柚子快報邀請碼778899分享:pyhton-8-scrapy
文章鏈接
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點和立場。
轉(zhuǎn)載請注明,如有侵權(quán),聯(lián)系刪除。