Python爬虫内容都是于2019上半年写的,关于某些网站的爬取技巧可能已经过时了,仅供参考。
scrapy 图片下载,自定义图片名称
学习 Scrapy 过程中发现用 Scrapy 下载图片时,总是以他们的 URL 的 SHA1 hash 值为文件名,如:
图片 URL:http://www.example.com/image.jpg
它的 SHA1 hash 值为:3afec3b4765f8f0a07b78f98c07b83f013567a0a
则下载的图片为:3afec3b4765f8f0a07b78f98c07b83f013567a0a.jpg
目的是下载的图片为:image.jpg或者xxx.jpg
可以通过编写 Pipeline 来实现。
1. 创建 scrapy 工程
进入目录下:
shift 键+鼠标右键,打开 dos 窗口
scrapy startproject airi_pic
目录结构<br>airi_pic.
│ scrapy.cfg
│
└─airi_pic
│ items.py
│ pipelines.py
│ settings.py
│ __init__.py
│
└─spiders
__init__.py
2. 在 items.py 中定义需要爬取信息的变量名称
import scrapy
#爬取煎蛋网图片
class JiandanPicItem(scrapy.Item):
image_url = scrapy.Field()
image_name = scrapy.Field()
3. 在 spiders 目录下创建 jiandan_pic_spider.py 文件,代码如下
import scrapy
from airi_pic.items import JiandanPicItem
import base64
Page = 0
class JiandanPicSpider(scrapy.Spider):
name = 'jiandan_pic'
start_urls = ['http://jandan.net/ooxx/page-1#comments']
def parse(self, response):
global Page
sel = scrapy.Selector(response)
image_urls = sel.xpath(
'//ol[@class="commentlist"]//div[@class="row"]/div[@class="text"]//span[@class="img-hash"]/text()').extract()#爬取到的html和实际略有出入
image_names = sel.xpath(
'//ol[@class="commentlist"]//div[@class="row"]/div[@class="text"]/span[@class="righttext"]/a/text()').extract()
new_urls = []
for xx in image_urls: # 获取的url需要转换编码
url = base64.b64decode(xx).decode('utf-8')
new_urls.append('https:' + url)
item = JiandanPicItem()
item['image_url'] = new_urls
item['image_name'] = image_names
yield item
while Page < 2:#控制爬取的页数
next_page = response.xpath('//div[@class="cp-pagenavi"]/a[@class="next-comment-page"]/@href')#获取“下一页"的具体网址
if next_page:
url = response.urljoin(next_page[0].extract())
yield scrapy.Request(url, self.parse)
Page += 1
4. 下载图片需要配置 pipelines 文件
from scrapy.pipelines.images import ImagesPipeline
from scrapy.exceptions import DropItem
from scrapy import Request
class JiandanPicPipeline(ImagesPipeline):
def file_path(self, request, response=None, info=None):
item = request.meta.get('item')#注意注意注意!!!,这里有坑,不能再使用request.meta['item']
index = request.meta.get('index')
# print(request.url)
# print(index)
image_name = item['image_name'][index] + '.' + request.url.split('/')[-1].split('.')[-1]
file_name = "{0}/{1}".format('jiandan',image_name)
return file_name
def item_completed(self, results, item, info):
image_paths = [x['path'] for ok, x in results if ok]
if not image_paths:
raise DropItem('图片未下载好')
return item
def get_media_requests(self, item, info):
for image_url in item['image_url']:
yield Request(image_url, meta={'item': item, 'index': item['image_url'].index(image_url)})
****5.settings.py****
ITEM_PIPELINES={
# 'airi_pic.pipelines.AiriPicPipeline':1
'airi_pic.pipelines.JiandanPicPipeline':1
}
IMAGES_STORE='pic'#图片保存目录路径
IMAGES_EXPIRES = 90
****6. 与 scrapy.cfg 同级目录下新建 start.py****
from scrapy import cmdline
cmdline.execute("scrapy crawl jiandan_pic".split(' '))
运行 start.py 文件即可。
本文作者为hresh,转载请注明。