2021-07-26

周一学习小结

针对国外的一些网站,进行了相关的学习

确定爬取的对象

在浏览器F12打开查看页面元素,分析一下这个网站的情况,可以看到幻灯片的图片地址藏在这个id=supersized的ul标签里面,也看到页面导航栏的元素是id=menu的ul标签下面,粗略分析之后,我们才来开始安装环境也写代码。

搭建python环境(docker)

docker环境不用说啦,一条语句就可以搞定的事情

我自己使用的是3.5的版本,其他版本请随意

docker pull python:3.5

进入容器安装爬虫框架

pip install scrapy

创建爬虫项目

scrapy startproject CrawlImages

命令行调试爬取对象的页面元素

scrapy shell http://hideakihamada.com

# 使用选择器输出页面的元素

response.css('#menu').css('a').xpath('@href').extract()

# 可以看到正常输出导航栏的菜单元素

# 接下来输出幻灯片的地址

response.css('#supersized')

瓦特,这是怎么回事,明明页面有的元素,这个万能的爬虫选择器为什么没法get到我要的数据呢。还是得好好思考一下,我脑子一下子复杂起来,懒加载?后端渲染数据?前端渲染数据?不知道什么回事,我在浏览器页面审核元素找了找,发现了更多的秘密,原来在scrapt里面还有后面才渲染出来的变量,存了特别多的照片url。直觉告诉我,这个网站还没全部加载完就被我的小虫虫先爬了一下,于是后面加载的数据小虫虫就拿不到数据了。于是找了一下相关插件,先不找是不是最强的,找个能用的就好,这个插件就是辅助小虫虫在拿到页面之前把网站先全部加载完,不管该网站用什么技术去渲染。

安装渲染网页的插件

专门渲染网页的插件——splash,docker安装即可

docker run -p 8050:8050 --name=splash scrapinghub/splash

#查看容器的ip地址

docker inspect splash

可以用主机ip加端口浏览器访问是不是能正常打开,能的话就恭喜你了,下面我们继续分析

爬虫代码

# 在项目 CrawlImagesItem 里面加个字段可以保存url的

img_url = scrapy.Field()

爬虫配置

# 在settings文件里面添加配置项

SPLASH_URL = 'http://172.17.0.2:8050' #这个ip一定要通的,不然小虫虫访问不到就没用了

#下载器中间件

DOWNLOADER_MIDDLEWARES = {

'scrapy_splash.SplashCookiesMiddleware': 723,

'scrapy_splash.SplashMiddleware': 725,

'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware': 810,

}

SPIDER_MIDDLEWARES = {

'scrapy_splash.SplashDeduplicateArgsMiddleware': 100,

}

# 去重过滤器

DUPEFILTER_CLASS = 'scrapy_splash.SplashAwareDupeFilter'

# 使用Splash的Http缓存

HTTPCACHE_STORAGE = 'scrapy_splash.SplashAwareFSCacheStorage'

爬虫代码

# CrawlImages.py

name = "CrawlImages"

allowed_domains = ["hideakihamada.com"]

start_urls = [

"http://hideakihamada.com",

]

# 在小虫虫发起请求之前,需要接一下刚才那个页面渲染插件

def start_requests(self):

for url in self.start_urls:

yield SplashRequest(url=url, callback=self.parse, args={'wait':1}, endpoint='render.html')

def parse(self, response):

images_item = CrawlImagesItem()

images_item['img_url'] = []

#获取页面的url

images = response.css("#supersized").css('img').xpath('@src').extract()

# 这里输出看是不是正常能输出渲染后的数据

print(images)

for image in images:

images_item['img_url'].append(image)

yield images_item

接下来运行代码一步步调试

scrapy crawl CrawlImages

print(images)能输出元素出来,说明刚才的那个插件没问题了,继续往下走

一个网站多个菜单,我们需要让小虫虫去自动发现爬取其他页面的数据

还是这个文件里面 CrawlImages.py

name = "CrawlImages"

allowed_domains = ["hideakihamada.com"]

start_urls = [

"http://hideakihamada.com",

]

# 懒得去设置菜单缓存或者去重了,直接在刚才命令行那里copy来的

tmp_nav = [

'/people', '/artists', '/family', '/haruandmina', '/haruandmina-2', 'http://www.one-day.jp/', '/goinggrain',

'/tokyosomewhere', '/myplanet-2014', '/myplanet-2017', '/akikokikuchi-2016', '/toshikiseto-2017',

'/editorial-2014', '/editorial-2015', '/editorial-2016', '/editorial-2017', '/editorial-2018',

'/lifestyle-2013', '/lifestyle-2014', '/lifestyle-2015', '/lifestyle-2016', '/lithuania', '/taiwan',

'/india-2014', '/egypt-2014', '/usa-2014', '/germany-2015', '/japan-tottori-2014', '/japan-kitakyushu',

'/japan-kagoshima-2015', '/shodoshima-2013', '/shodoshima-2014', '/studiocamelhouse',

'/toyota-municipal-museum-of-art', '/video', '/books', '/web', '/catalog', '/magazines', '/commercials', '/cv',

'/blog', '/contact'

]

for i_nav in tmp_nav:

start_urls.append("http://hideakihamada.com"+i_nav)

不要忘了刚才在分析问题的时候遗漏的重要东西,就是该网站把很多图片的url渲染到js变量里面了,我们需要拿下来扔到item里面,于是改装一下parse方法

def parse(self, response):

chicho_item = ChichoItem()

chicho_item['img_url'] = []

# 获取script标签里面所有的url

tmp_data = response.xpath('//script[@type="text/javascript"]')[1].extract()

my_tmp_data = re.compile(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*,]|(?:%[0-9a-fA-F][0-9a-fA-F]))+')

image_urls = re.findall(my_tmp_data, tmp_data)

regex = re.compile(r'^.*?(jpg|png|jpeg)$')

for image_url in image_urls:

if regex.search(image_url):

chicho_item['img_url'].append(image_url)

#获取页面的url

images = response.css("#supersized").css('img').xpath('@src').extract()

for image in images:

chicho_item['img_url'].append(image)

yield chicho_item

我们的目的是搞事情阿,就是要下载发现的所有图片,所以当然少不了下载图片的代码

接下来在settings文件里面加上配置

# 图片存储设置

IMAGES_STORE = '/www/images' //路径看着办,根据自己项目情况修改

# 里面的PIPELINES指向的是项目pipelines文件的类

ITEM_PIPELINES = {

'Chicho.pipelines.CrawlImagesPipeline': 2,

'Chicho.pipelines.MyImagesPipeline': 1

}

USER_AGENT = "Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20100101 Firefox/10.0"

写pipelines文件的代码

from scrapy.pipelines.images import ImagesPipeline

import scrapy

class CrawlImagesPipeline(object):

def process_item(self, item, spider):

return item

class MyImagesPipeline(ImagesPipeline):

def get_media_requests(self, item, info):

for url in item['img_url']:

yield scrapy.Request(url, meta={'item': item})

你可能感兴趣的:(2021-07-26)