混金融圈混久了,感觉金融就是一个坑,越陷越深。学习分析,除了会报表外,还要懂得数据处理,所以学习编程是跑不了的。然后上半年不断学习python的数据分析用法,然后。。。又发现没有数据你什么都分析不了。。。于是乎又要学习网站爬虫。感觉自己越学越杂了。
▌前言
前段时间学习了用Python 的Urllib 和BeautifulSoup爬虫,感觉效率不高。于是又去学了pyspider。鉴于网上对pyspider的教学不多,我就按照崔庆才的个人博客上分享的小白进阶之Scrapy第四篇(图片下载管道篇) 进行了分析。教程里面是用到scrapy的,鉴于本人不会scrapy,于是自己按照之前学的知识用pyspider爬了下来,代码中的"文件保存部分"是直接用了崔庆才的代码,感谢崔庆才。
▌目标网址
首先,建立一个项目并输入网址:www.mzitu.com/all, 然后点击运行。
▌获取链接
然后“follows”后面会出现红点, 证明了获取链接www.mzitu.com/all 成功。
▌定义范围
然后再点击绿色的图标获取www.mzitu.com/all 下的所有链接。成功了。 但问题是有些链接我们是不需要的,所以我们要定义获取的范围。
虽然pyspider本身已经提供了很好的css selector,但有时候获取效果不大理想,所以我们可以直接用chrome的F12进行分析获取。 先点击要获取的范围,然后在代码处右键选取css selector。 本教程只是为了练习,没有必要将全部链接都获取,所以我只选取了05月份的链接作为获取范围。
▌删除多余链接
回到代码处添加刚才的选取范围,是不是发现多余的链接都没有了呢? #提取指定div.all > ul:nth-child(3) > li:nth-child(1)里面的部分连接
#提取指定div.all > ul:nth-child(3) > li:nth-child(1)里面的部分连接
#如果想获取全站的图片,只需要改为'div.all a[href^="http"]'
@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
for each in response.doc('div.all > ul:nth-child(3) > li:nth-child(1) a[href^="http"]').items():
self.crawl(each.attr.href, callback=self.detail_page)
▌发现问题
获取对应链接后,再随便点击左图上绿色的箭头,然后选择“web”, 接下来会看到每个页面只显示一张图片,接下来要处理的问题是利用循环遍历57个页面并获取图片。
▌获得页码数
首先分析页面的规律会发现,最大页数通常在底部页码链接中的倒数第二个,或者是顺数第七个。既然是固定的话,那么直接获取css selector就可以了。
▌遍历图片
然后用while循环就能获取对应页面了。
#获取某一页面后,每页只显示一张图片,所以要循环获取所有连接
@config(priority=2)
def detail_page(self, response):
self.page_num = 1
self.page_total = int(response.doc('div.pagenavi > a:nth-child(7)').text()) #获取总图片页面数
self.base_url = response.url + '/'
#循环获取所有连接
while self.page_num <= self.page_total:
url = self.base_url + str(self.page_num)
self.crawl(url, callback=self.domain_page)
self.page_num += 1
▌全部代码:
# Created on 2017-05-22 09:13:19
#分c君_BingWong
# Project: meizitu
#直接复制到pyspider里面就可以运行了
from pyspider.libs.base_handler import *
import os
DIR_PATH = '/mm'
class Handler(BaseHandler):
crawl_config = {
}
def __init__(self):
self.deal = Deal()
@every(minutes=24 * 60)
def on_start(self):
self.crawl('http://www.mzitu.com/all', callback=self.index_page)
self.deal=Deal()
#提取指定div.all > ul:nth-child(3) > li:nth-child(1)里面的部分连接
#如果想获取全站的图片,只需要改为'div.all a[href^="http"]'
@config(age=10 * 24 * 60 * 60)
def index_page(self, response):
for each in response.doc('div.all > ul:nth-child(3) > li:nth-child(1) a[href^="http"]').items():
self.crawl(each.attr.href, callback=self.detail_page)
#获取某一页面后,每页只显示一张图片,所以要循环获取所有连接
@config(priority=2)
def detail_page(self, response):
self.page_num = 1
self.page_total = int(response.doc('div.pagenavi > a:nth-child(7)').text()) #获取总图片页面数
self.base_url = response.url + '/'
#循环获取所有连接
while self.page_num <= self.page_total:
url = self.base_url + str(self.page_num)
self.crawl(url, callback=self.domain_page)
self.page_num += 1
def domain_page(self, response):
name = response.doc('.main-title').text() #获取网页标题
dir_path = self.deal.mkDir(name) #建立目录
if dir_path:
imgs = response.doc('p img').items() #获取页面图片
count = 1
for img in imgs:
url = img.attr.src
if url:
extension = self.deal.getExtension(url)
file_name = name + str(count) + '.' + extension
count += 1
self.crawl(img.attr.src, callback=self.save_img,
save={'dir_path': dir_path, 'file_name': file_name})
return {"name":name,}
#保存图片
def save_img(self, response):
content = response.content
dir_path = response.save['dir_path']
file_name = response.save['file_name']
file_path = dir_path + '/' + file_name
self.deal.saveImg(content, file_path)
class Deal:
def __init__(self):
self.path = DIR_PATH
if not self.path.endswith('/'):
self.path = self.path + '/'
if not os.path.exists(self.path):
os.makedirs(self.path)
def mkDir(self, path):
path = path.strip()
dir_path = self.path + path
exists = os.path.exists(dir_path)
if not exists:
os.makedirs(dir_path)
return dir_path
else:
return dir_path
def saveImg(self, content, path):
f = open(path, 'wb')
f.write(content)
f.close()
def saveBrief(self, content, dir_path, name):
file_name = dir_path + "/" + name + ".txt"
f = open(file_name, "wb+")
f.write(content.encode('utf-8'))
def getExtension(self, url):
extension = url.split('.')[-1]
return extension
▌最后
别忘了在 def on_start 继承Deal()这个类,要不然保存不了。其实要beautifulsoup和urllib都可以达到同样的效果,不过会改用正则表达式获取相应内容。