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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

用Scrapy爬取王者皮肤海报~

發(fā)布時(shí)間:2024/1/1 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 用Scrapy爬取王者皮肤海报~ 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

文章目錄

  • 咳咳,這里可以直接下載皮膚
  • 這篇博客的由來
  • 先看一下成品。
  • 一、口水話說說,ImagePipeline
    • 0、一般來說,簡單使用ImagesPipeline。
    • 1.ImagePipeline可以做這樣的事情
    • 2.進(jìn)一步配置setting.py
    • 3.我這樣寫爬蟲spider.py
    • 4.上代碼(我的item.py/skin.py(我寫的爬蟲類))
    • 5.寫ItemPipeline,(Customize ItemPipeline)
  • 二、真正要學(xué)習(xí)的就是這三個(gè)函數(shù)了
      • 6.1 file_path(self, request, response=None, info=None, *, item=None)
      • 6.2 get_media_requests(item, info)
      • 6.3item_completed(results, item, info)


咳咳,這里可以直接下載皮膚

我把爬到的照片上傳到我的資源了。感興趣的可以下載來看看噢。
——免費(fèi)傳送門

這篇博客的由來

當(dāng)然是因?yàn)槲覍W(xué)習(xí)之余,喜歡打打王者上上分 (下面是我王者個(gè)人主頁,啊還沒上過榮耀…)

以及因?yàn)?#xff0c;我要學(xué)習(xí) Scrapy 的ImagesPipeline,爬圖片


先看一下成品。



爬蟲結(jié)束后的日志,只爬到了93個(gè)items(93個(gè)英雄的皮膚,當(dāng)然皮膚不只93)

以下內(nèi)容,有一些是翻譯的,我會附上文檔的英文原文。


一、口水話說說,ImagePipeline

想要邊學(xué)習(xí)scrapy 框架,邊學(xué)習(xí)英文?
想同時(shí)提高scrapy框架的掌握程度,和英文閱讀水平?

那就有空多看scrapy權(quán)威文檔(authoritative document

At first

提到ImagesPipeline 就要先提它的 “本體” ——FilesPipeline
因?yàn)?ImagesPipeline 是 FilesPipeline的一個(gè)擴(kuò)展(extension)

The ImagesPipeline is an extension of the FilesPipeline

嗯,就提這么多。


0、一般來說,簡單使用ImagesPipeline。

(當(dāng)然先創(chuàng)建scrapy 項(xiàng)目。)

只需要:
1.啟用媒體管道(Enabling your Media Pipeline):
在setting.py中的ITEM_PIPELINES添加
'scrapy.pipelines.images.ImagesPipeline': 1

2.配置存儲目標(biāo)地址(configure the target storage)
要寫一個(gè) 有效的 地址,否則即便完成了第一步也不能啟用pipeline
在setting.py中設(shè)置 IMAGES_STORE setting:
IMAGESS_STORE = '/path/to/valid/dir'

我存到了scrapy project根目錄。就是與scrapy.cfg相同的文件夾

3.items.py類的配置
很簡單,添兩個(gè)字段。

import scrapy class MyItem(scrapy.Item):# ... other item fields ...image_urls = scrapy.Field() #務(wù)必添加的images = scrapy.Field() # 務(wù)必添加的

image_urls ,一個(gè)list,存放圖片url (http://…jpg/png等)
images,一個(gè)RESULT,一個(gè)2元素元組的列表
每個(gè)元組將包含 (success, file_info_or_error)
·
下面是results參數(shù)的一個(gè)典型值:

[(True,{'checksum': '2b00042f7481c7b056c4b410d28f33cf','path': 'full/0a79c461a4062ac383dc4fade7bc09f1384a3910.jpg','url': 'http://www.example.com/files/product1.pdf','status': 'downloaded'}),(False,Failure(...))]

4.寫爬蟲(spider.py),返回item(圖片url列表)

簡單使用的時(shí)候,存儲的圖片。

存在一個(gè)full目錄下
圖片文件名是根據(jù)原始url計(jì)算SHA1 hash值后進(jìn)行存儲;
大概長這樣:

這顯然滿足不了妹子的需求,人家只想看中文字的圖片名

所以要進(jìn)一步配置setting.py


1.ImagePipeline可以做這樣的事情

1.如生成縮略圖

generating thumbnails

2.根據(jù)大小過濾圖像。

filtering the images based on their size.

3.允許重定向 (其實(shí)皮膚海報(bào)的url是重定向的,但有一個(gè)小規(guī)律,可以不用重定向)

Allowing redirections
默認(rèn)情況下(By default),
媒體管道會忽略重定向( ignore redirects,)
例如,一個(gè)指向媒體文件URL請求的HTTP重定向?qū)⒁馕吨襟w下載失敗。

4.當(dāng)然還可以自己指定文件名、文件夾名

5.避免下載最近下載的文件

指定延遲天數(shù)

# 120 days of delay for files expiration FILES_EXPIRES = 120# 30 days of delay for images expiration IMAGES_EXPIRES = 30

2.進(jìn)一步配置setting.py

我創(chuàng)建的scrapy項(xiàng)目:叫做KingshonorskinPipeline

setting.py中:

ROBOTSTXT_OBEY = False #首先,一般都不遵循Robot協(xié)議DEFAULT_REQUEST_HEADERS = {'Accept': 'application/json, text/javascript, */*; q=0.01','Accept-Language': 'en','User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.182 Safari/537.36' } # 默認(rèn)請求頭ITEM_PIPELINES = {'kingshonerSkin.pipelines.KingshonerskinPipeline': 300,# 'scrapy.pipelines.images.ImagesPipeline': 1 } # 注釋了默認(rèn)的ImagePipeline, # 同時(shí)啟用,我自己customize(自己寫的)KingshonerskinPipelineIMAGES_STORE = './王者榮耀皮膚' #我設(shè)置的文件存儲目錄 IMAGES_URLS_FIELD = 'skin_urls' # 我給默認(rèn)的image_urls 改成了 skin_urls IMAGES_RESULT_FIELD = 'skin_results' # 我給默認(rèn)的image 改成了 skin_results

我的setting.py的部分截圖

3.我這樣寫爬蟲spider.py

從這里開始爬:

英雄資料列表頁-英雄介紹-王者榮耀官方網(wǎng)站-騰訊游戲https://pvp.qq.com/web201605/herolist.shtml

先大概分析


進(jìn)入每個(gè)英雄的頁面后,


我一般在pycharm console 先來交互式的編程

導(dǎo)入requests,Beautiful 來一步一步“進(jìn)入網(wǎng)頁”,爬取信息。

代碼有效就復(fù)制到spider.py里面

免得一次性寫好爬蟲文件(spider.py)再來debug,

導(dǎo)入庫

直接requests.get(url)
沒有加headers或者其他參數(shù),直接在右邊看到,Resposne 200了
這網(wǎng)站,沒什么反扒

分析我用select方法定位標(biāo)簽

接著我

for i in soup.select('.herolist-content > ul > li > a'): print(i.text)

結(jié)果print一些亂碼出來:我發(fā)現(xiàn)是response.encoding的問題。

改一下encoding,就正常顯示中文字。

到了這里說明沒有頁面渲染每個(gè)英雄的url都能拿到
·
接著進(jìn)入單個(gè)英雄,就拿瑤瑤分析吧
https://pvp.qq.com/web201605/herodetail/505.shtml

用select抓一下標(biāo)簽


結(jié)果抓了個(gè)寂寞
要么我寫錯了select,要么網(wǎng)頁動態(tài)渲染了。
但我向來不會犯這樣寫錯小錯誤,結(jié)果還真是渲染了。
Refresh了網(wǎng)頁,這個(gè)url真正html代碼:

經(jīng)過一番對比
發(fā)現(xiàn)background_url(網(wǎng)頁背景皮膚海報(bào)的url)是一樣的,下面pic-pf標(biāo)簽不一樣
·
真正需要的就是background_url
·
因?yàn)橄嗤⑿鄣钠つw海報(bào)url,就后面的數(shù)字在遞增

所以到現(xiàn)在,spider.py真正要解決的是
1.每個(gè)hero對應(yīng)的id
2.皮膚的數(shù)量和名字

4.上代碼(我的item.py/skin.py(我寫的爬蟲類))

# items.py import scrapyclass KingshonerskinItem(scrapy.Item):skin_urls = scrapy.Field() # 必須要有的字段,list,存放皮膚urlskins_name = scrapy.Field() # list,存放皮膚nameskin_results = scrapy.Field() # 必須要有的字段,result 存放...hero_name = scrapy.Field() # str, 英雄中文名 # spider.py import scrapy from bs4 import BeautifulSoup from scrapy import Request import re from kingshonerSkin.items import KingshonerskinItemclass SkinSpider(scrapy.Spider):name = 'skin'start_urls = ['https://pvp.qq.com/web201605/herolist.shtml']def parse(self, response): # 進(jìn)入每個(gè)英雄的皮膚所在頁面soup = BeautifulSoup(response.text,'html.parser')for i in soup.select('.herolist-content > ul > li > a'):url_id = re.findall(r'/\d+.shtml',i.get('href'))[0] # 拿到每個(gè)英雄對應(yīng)的idyield Request(url='https://pvp.qq.com/web201605/herodetail'+url_id, callback=self.parse_skin)# 按照id,組成每個(gè)英雄的url,去yield Requestdef parse_skin(self, response):item = KingshonerskinItem()soup = BeautifulSoup(response.text, 'html.parser')skin_id = 'https:' + re.findall(r'//.*.jpg',soup.select_one('.wrapper > div').get('style'))[0].replace('1.jpg','{}.jpg')# 將background_url 變成通用的skins_name = soup.select_one('.pic-pf > ul').get('data-imgname').split('|') # 皮膚名字列表hero_name = soup.select_one('h2.cover-name').texturls = []for i in range(len(skins_name)):skins_name[i] = skins_name[i].split('&')[0] # 清理多余的符號“&3”urls.append(skin_id.format(i+1))item['hero_name'] = hero_nameitem['skin_urls'] = urlsitem['skins_name'] = skins_namereturn item

5.寫ItemPipeline,(Customize ItemPipeline)

如果簡單使用ImagesPipeline
無需寫這個(gè)類,
只用:啟用’scrapy.pipelines.images.ImagesPipeline’: 1,
甚至不禁用自己寫的pipeline.py也可以

ITEM_PIPELINES = {'kingshonerSkin.pipelines.KingshonerskinPipeline': 300,'scrapy.pipelines.images.ImagesPipeline': 1 }

當(dāng)然,我們要處理英雄和皮膚的對應(yīng)關(guān)系。
自己寫ItemPipeline.

我先上我的itempipeline.py代碼

from scrapy import Request from scrapy.pipelines.images import ImagesPipelineclass KingshonerskinPipeline(ImagesPipeline):def file_path(self, request, response=None, info=None, *, item):skin_num = int(request.url[-5]) - 1 # 海報(bào)url和海報(bào)名字對應(yīng)上。return f'{item["hero_name"]}/{item["skins_name"][skin_num]}.jpg'def get_media_requests(self, item, info):# for i in item['skins_name']:# yield Request(i)return [Request(i) for i in item['skin_urls']]

二、真正要學(xué)習(xí)的就是這三個(gè)函數(shù)了

6.1 file_path(self, request, response=None, info=None, *, item=None)

This method is called once per downloaded item.
It returns the download path of the file originating from the specified

·
這個(gè)方法對每個(gè)下載的item調(diào)用一次。
返回來自指定的文件的下載路徑

override this method to customize the download path of each file
覆蓋/重寫這個(gè)函數(shù)就可以自定義存儲文件(圖片)的路徑

對于這個(gè)函數(shù)的幾個(gè)參數(shù),

1.在我寫的pipeline中,item=None的None去掉了。
于是就可以使用我放在item里面的字段(hero_name 、skins_name)
在指定英雄和皮膚的對應(yīng)關(guān)系

def file_path(self, request, response=None, info=None, *, item):skin_num = int(request.url[-5]) - 1 # 海報(bào)url和海報(bào)名字對應(yīng)上。return f'{item["hero_name"]}/{item["skins_name"][skin_num]}.jpg'

2.我嘗試用response.meta去傳遞(hero_name 、skins_name)
但是失敗了。不知道原因出自哪里。
·
3.不知道這個(gè)info怎么用
哪天發(fā)現(xiàn)了,再加到這里
·
4.request,就相當(dāng)于request
文檔里面給了一用request.url的后綴作為圖片名的例子

import os from urllib.parse import urlparsefrom scrapy.pipelines.files import FilesPipelineclass MyFilesPipeline(FilesPipeline):def file_path(self, request, response=None, info=None, *, item=None):return 'files/' + os.path.basename(urlparse(request.url).path)

6.2 get_media_requests(item, info)

As seen on the workflow,
the pipeline will get the URLs of the images to download from the item.
return a Request for each file URL:

·
這個(gè)函數(shù)很簡單,就是作為一個(gè) 生成器
不斷地 return a Request for each file URL:

def get_media_requests(self, item, info):# for i in item['skins_name']:# yield Request(i)return [Request(i) for i in item['skin_urls']]

代碼中,注釋部分和下面的return是等價(jià)的。


Those requests will be processed by the pipeline and,
when they have finished downloading,
the results will be sent to the item_completed() method, as a list of 2-element tuples.
Each tuple will contain (success, file_info_or_error)

·
這些請求將由管道處理,
當(dāng)它們完成下載后,
結(jié)果(方法:item_completed()的 result參數(shù) )將作為一個(gè)包含2個(gè)元素的元組列表發(fā)送到
item_completed()方法。
每個(gè)元組將包含(success, file_info_or_error)


我就不翻譯了。

6.3item_completed(results, item, info)

The ImagesPipeline.item_completed() method is called
when all image requests for a single item have completed
(either finished downloading, or failed for some reason).

·
當(dāng)單個(gè)item的所有圖像請求都完成
(或者下載完成,或者由于某些原因失敗)時(shí),
將調(diào)用ImagesPipeline.item_completed()方法。

we store the downloaded file paths (passed in results) in the file_paths item field,
and we drop the item if it doesn’t contain any files:

·
我們將下載的文件路徑(傳到result),存儲在file_paths 的item字段中,
如果item不包含任何文件,我們就刪除它:

下面附一下 文檔給的,實(shí)現(xiàn)這個(gè)方法的an example

from itemadapter import ItemAdapter from scrapy.exceptions import DropItemdef item_completed(self, results, item, info):file_paths = [x['path'] for ok, x in results if ok]if not file_paths:raise DropItem("Item contains no files")adapter = ItemAdapter(item)adapter['file_paths'] = file_paths return item

result 是一個(gè)包含兩個(gè)元素的元組列表 (a list of 2-element tuples.)

# a typical value of the results argument: [(True,{'checksum': '2b00042f7481c7b056c4b410d28f33cf','path': 'full/0a79c461a4062ac383dc4fade7bc09f1384a3910.jpg','url': 'http://www.example.com/files/product1.pdf','status': 'downloaded'}),(False,Failure(...))]

我沒有覆蓋這個(gè)item_completed函數(shù),
我在file_paths,寫英雄名字和皮膚的對應(yīng)關(guān)系了。
這個(gè)函數(shù)就是,可以進(jìn)一步處理 已經(jīng)下載好的 每個(gè)item

顯然我們不用進(jìn)一步處理item


運(yùn)行

scrapy crawl skin

注意:如果沒有圖片產(chǎn)生,看看也沒有下面的報(bào)錯。

WARNING: Disabled KingshonerskinPipeline: ImagesPipeline requires installing Pillow 4.0.0 or later
有的話,說明缺少必要的第三發(fā)庫pillow, 就:

pip install pillow

然后重新

scrapy crawl skin

就這些了,祝大家上分愉快~

總結(jié)

以上是生活随笔為你收集整理的用Scrapy爬取王者皮肤海报~的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。