整合营销服务商

电脑端+手机端+微信端=数据同步管理

免费咨询热线:

Python网络爬虫-爬取QQ空间相册

析QQ空间

登录QQ空间

爬取第一步,分析站点,首先需要知道如何登录QQ空间。最初想法是用requests库配置登录请求,模拟登录,但是不久便放弃了这一思路,请看下图↓

login

根据登录按钮绑定的监听事件可以追踪到该按钮的点击事件如下:

login function

账号加密是必然的,但这一堆堆的代码真心不好解析,有耐心的勇士尽情一试!

在排除这种登录方法后,选择selenium模拟用户登录不失为省时省力的方法,而且我们只是需要通过selenium完成登录,获取到Cookies和后面讲述的g_tk参数后,就可以停用了,所以效率并不太低。

分析空间相册

登录以后,页面会跳转至 [https://user.qzone.qq.com/{QQ_NUMBER}](javascript:;), 这时把鼠标移到导航栏你会发现,所有的导航栏链接都是javascript:; 。没错就是这么坑,一切都是暗箱操作。

当然这并不难处理,使用调试工具捕获点击后产生的请求,然后过滤出正确的请求包即可。因为网络包非常多,那么怎么过滤呢,猜想相册数据的API必然会返回个列表list,尝试过滤list然后逐个排除,最后定位到请求包。下面是通过fcg_list过滤后的数据包,列表信息以jsonp格式返回,稍作处理即可当做json格式来读取(后面有讲)。

album list

从Headers和Response可以分别获取到两组重要信息:

  1. request 获取相册列表所需的请求信息,包括请求链接和参数
  2. response 数据包包含的所有相册的信息,是每个相册所含照片对应的请求包参数的数据来源

先看请求包:

# url
https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/fcg_list_album_v3

# args
g_tk: 477819917
callback: shine0_Callback
t: 691481346
hostUin: 123456789
uin: 123456789
appid: 4
inCharset: utf-8
outCharset: utf-8
source: qzone
plat: qzone
format: jsonp
notice: 0
filter: 1
handset: 4
pageNumModeSort: 40
pageNumModeClass: 15
needUserInfo: 1
idcNum: 4
callbackFun: shine0
_: 1551788226819

其中hostUin, uin都是QQ号,g_tk是必须的且每次重新登录都会更新(后面有讲如何获取),其它有些参数不是必须的,我尝试后整理出如下请求参数:

query = {
 'g_tk': self.g_tk,
 'hostUin': self.username,
 'uin': self.username,
 'appid': 4,
 'inCharset': 'utf-8',
 'outCharset': 'utf-8',
 'source': 'qzone',
 'plat': 'qzone',
 'format': 'jsonp'
}

接下来看jsonp格式的跨域响应包:

shine0_Callback({
 "code":0,
 "subcode":0,
 "message":"",
 "default":0,
 "data":
{
 "albumListModeSort" : [
 {
 "allowAccess" : 1,
 "anonymity" : 0,
 "bitmap" : "10000000",
 "classid" : 106,
 "comment" : 11,
 "createtime" : 1402661881,
 "desc" : "",
 "handset" : 0,
 "id" : "V13LmPKk0JLNRY",
 "lastuploadtime" : 1402662103,
 "modifytime" : 1408271987,
 "name" : "毕业季",
 "order" : 0,
 "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/a\/dIY29GUbJgAA",
 "priv" : 1,
 "pypriv" : 1,
 "total" : 4,
 "viewtype" : 0
 },

shine0_Callback是请求包的callbackFun参数决定的,如果没这个参数,响应包会以_Callback作为默认名,当然这都不重要。所有相册信息以json格式存入albumListModeSort中,上面仅截取了一个相册的信息。

相册信息中,name代表相册名称,id作为唯一标识可用于请求该相册内的照片信息,而pre仅仅是一个预览缩略图的链接,无关紧要。

分析单个相册

与获取相册信息类似,进入某一相册,使用cgi_list过滤数据包,找到该相册的照片信息

photo list

同样的道理,根据数据包可以获取照片列表信息的请求包和响应信息,先看请求:

# url
https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_list_photo

# args
g_tk: 477819917
callback: shine0_Callback
t: 952444063
mode: 0
idcNum: 4
hostUin: 123456789
topicId: V13LmPKk0JLNRY
noTopic: 0
uin: 123456789
pageStart: 0
pageNum: 30
skipCmtCount: 0
singleurl: 1
batchId: 
notice: 0
appid: 4
inCharset: utf-8
outCharset: utf-8
source: qzone
plat: qzone
outstyle: json
format: jsonp
json_esc: 1
question: 
answer: 
callbackFun: shine0
_: 1551790719497

其中有几个关键参数:

  1. g_tk - 与相册列表参数一致
  2. topicId - 与相册列表参数中的id一致
  3. pageStart - 本次请求照片的起始编号
  4. pageNum - 本次请求的照片数量

为了一次性获取所有照片,可以将pageStart设为0,pageNum设为所有相册所含照片的最大值。

同样可以对上面的参数进行简化,在相册列表请求参数的基础上添加topicId,pageStart和pageNum三个参数即可。

下面来看返回的照片列表信息:

shine0_Callback({
 "code":0,
 "subcode":0,
 "message":"",
 "default":0,
 "data":
{
 "limit" : 0,
 "photoList" : [
 {
 "batchId" : "1402662093402000",
 "browser" : 0,
 "cameratype" : " ",
 "cp_flag" : false,
 "cp_x" : 455,
 "cp_y" : 388,
 "desc" : "",
 "exif" : {
 "exposureCompensation" : "",
 "exposureMode" : "",
 "exposureProgram" : "",
 "exposureTime" : "",
 "flash" : "",
 "fnumber" : "",
 "focalLength" : "",
 "iso" : "",
 "lensModel" : "",
 "make" : "",
 "meteringMode" : "",
 "model" : "",
 "originalTime" : ""
 },
 "forum" : 0,
 "frameno" : 0,
 "height" : 621,
 "id" : 0,
 "is_video" : false,
 "is_weixin_mode" : 0,
 "ismultiup" : 0,
 "lloc" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!",
 "modifytime" : 1402661792,
 "name" : "QQ图片20140612104616",
 "origin" : 0,
 "origin_upload" : 0,
 "origin_url" : "",
 "owner" : "123456789",
 "ownername" : "123456789",
 "photocubage" : 91602,
 "phototype" : 1,
 "picmark_flag" : 0,
 "picrefer" : 1,
 "platformId" : 0,
 "platformSubId" : 0,
 "poiName" : "",
 "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/a\/dIY29GUbJgAA&bo=pANtAgAAAAABCeY!",
 "raw" : "http:\/\/r.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/r\/dIY29GUbJgAA",
 "raw_upload" : 1,
 "rawshoottime" : 0,
 "shoottime" : 0,
 "shorturl" : "",
 "sloc" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!",
 "tag" : "",
 "uploadtime" : "2014-06-13 20:21:33",
 "url" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfSk58K2rQY!\/b\/dIY29GUbJgAA&bo=pANtAgAAAAABCeY!",
 "width" : 932,
 "yurl" : 0
 },
 // ...
 ]
 "t" : "952444063",
 "topic" : {
 "bitmap" : "10000000",
 "browser" : 0,
 "classid" : 106,
 "comment" : 1,
 "cover_id" : "NDN0sggyKs3smlOg6eYghjb0ZRsmAAA!",
 "createtime" : 1402661881,
 "desc" : "",
 "handset" : 0,
 "id" : "V13LmPKk0JLNRY",
 "is_share_album" : 0,
 "lastuploadtime" : 1402662103,
 "modifytime" : 1408271987,
 "name" : "毕业季",
 "ownerName" : "707922098",
 "ownerUin" : "707922098",
 "pre" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/a\/dIY29GUbJgAA",
 "priv" : 1,
 "pypriv" : 1,
 "share_album_owner" : 0,
 "total" : 4,
 "url" : "http:\/\/b171.photo.store.qq.com\/psb?\/V13LmPKk0JLNRY\/eSAslg*mYWaytEtLysg*Q*5Km91gIWfGuwSk58K2rQY!\/b\/dIY29GUbJgAA",
 "viewtype" : 0
 },
 "totalInAlbum" : 4,
 "totalInPage" : 4
}

返回的照片信息都存于photoList, 上面同样只截取了一张照片的信息,后面一部分返回的是当前相册的一些基本信息。totalInAlbum, totalInPage存储了当前相册总共包含的照片数及本次返回的照片数。而我们需要下载的图片链接则是url!

OK, 到此,所有请求和响应数据都分析清楚了,接下来便是coding的时候了。

确定爬取方案

  1. 创建qqzone类,初始化用户信息
  2. 使用Selenium模拟登录
  3. 获取Cookies和g_tk
  4. 使用requests获取相册列表信息
  5. 遍历相册,获取照片列表信息并下载照片

创建qqzone类

class qqzone(object):
 """QQ空间相册爬虫"""
 def __init__(self, user):
 self.username = user['username']
 self.password = user['password']

模拟登录

from selenium import webdriver
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import WebDriverExceptio

# ...

def _login_and_get_args(self):
 """登录QQ,获取Cookies和g_tk"""
 opt = webdriver.ChromeOptions()
 opt.set_headless()

 driver = webdriver.Chrome(chrome_options=opt)
 driver.get('https://i.qq.com/')
 # time.sleep(2)

 logging.info('User {} login...'.format(self.username))
 driver.switch_to.frame('login_frame')
 driver.find_element_by_id('switcher_plogin').click()
 driver.find_element_by_id('u').clear()
 driver.find_element_by_id('u').send_keys(self.username)
 driver.find_element_by_id('p').clear()
 driver.find_element_by_id('p').send_keys(self.password)
 driver.find_element_by_id('login_button').click()

 time.sleep(1)
 driver.get('https://user.qzone.qq.com/{}'.format(self.username))

此处需要注意的是:

  1. 使用selenium需要安装对应的webdriver
  2. 可以通过webdriver.Chrome()指定浏览器位置,否则默认从环境变量定义的路径查找
  3. 如果电脑打开浏览器较慢,可能需要在driver.get后sleep几秒

获取 Cookies

使用selenium获取Cookies非常方便

self.cookies = driver.get_cookies()

获取 g_tk

获取g_tk最开始可以说是本爬虫最大的难点,因为从网页中根本找不到直接写明的数值,只有各种函数调用。为此我全局搜索,发现好多地方都有其获取方式。

g_tk

最后选择了其中一处,通过selenium执行脚本的功能成功获取到了g_tk!

self.g_tk = driver.execute_script('return QZONE.FP.getACSRFToken()')

到此,selenium的使命就完成了,剩下的将通过requests来完成。

初始化 request.Session

接下来需要逐步生成请求然后获取数据。但是为方便起见,这里使用会话的方式请求数据,配置好cookie和headers,省的每次请求都设置一遍。

def _init_session(self):
 self.session = requests.Session()
 for cookie in self.cookies:
 self.session.cookies.set(cookie['name'], cookie['value'])
 self.session.headers = {
 'Referer': 'https://qzs.qq.com/qzone/photo/v7/page/photo.html?init=photo.v7/module/albumList/index&navBar=1',
 'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/72.0.3626.109 Safari/537.36'
 }

请求相册信息

获取相册信息,需要先封装好请求参数,然后通过session.get爬取数据,再通过正则匹配以json格式读取jsonp数据,最后解析所需的name和id。

def _get_ablum_list(self):
 """获取相册的列表信息"""
 album_url = '{}{}'.format(
 'https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/fcg_list_album_v3?',
 self._get_query_for_request())

 logging.info('Getting ablum list id...')
 resp = self.session.get(album_url)
 data = self._load_callback_data(resp)

 album_list = {}
 for item in data['data']['albumListModeSort']:
 album_list[item['name']] = item['id']

 return album_list

其中的参数组合来自下面的函数_get_query_for_request函数。

def _get_query_for_request(self, topicId=None, pageStart=0, pageNum=100):
 """获取请求相册信息或照片信息所需的参数

 Args:
 topicId: 每个相册对应的唯一标识符
 pageStart: 请求某个相册的照片列表信息所需的起始页码
 pageNum: 单次请求某个相册的照片数量

 Returns:
 一个组合好所有请求参数的字符串
 """
 query = {
 'g_tk': self.g_tk,
 'hostUin': self.username,
 'uin': self.username,
 'appid': 4,
 'inCharset': 'utf-8',
 'outCharset': 'utf-8',
 'source': 'qzone',
 'plat': 'qzone',
 'format': 'jsonp'
 }
 if topicId:
 query['topicId'] = topicId
 query['pageStart'] = pageStart
 query['pageNum'] = pageNum
 return '&'.join('{}={}'.format(key, val) for key, val in query.items())

其中的jsonp解析函数如下,主体部分就是一个正则匹配,非常简单。

def _load_callback_data(self, resp):
 """以json格式解析返回的jsonp数据"""
 try:
 resp.encoding = 'utf-8'
 data = loads(re.search(r'.*?\(({.*}).*?\).*', resp.text, re.S)[1])
 return data
 except ValueError:
 logging.error('Invalid input')

解析并下载照片

获取相册列表后,逐个请求照片列表信息,进而逐一下载

def _get_photo(self, album_name, album_id):
 """获取单个相册的照片列表信息,并下载该相册所有照片"""
 photo_list_url = '{}{}'.format(
 'https://h5.qzone.qq.com/proxy/domain/photo.qzone.qq.com/fcgi-bin/cgi_list_photo?',
 self._get_query_for_request(topicId=album_id))

 logging.info('Getting photo list for album {}...'.format(album_name))
 resp = self.session.get(photo_list_url)
 data = self._load_callback_data(resp)
 if data['data']['totalInPage'] == 0:
 return None

 file_dir = self.get_path(album_name)
 for item in data['data']['photoList']:
 path = '{}/{}.jpg'.format(file_dir, item['name'])
 logging.info('Downloading {}-{}'.format(album_name, item['name']))
 self._download_image(item['url'], path)

下载图片也是通过request,记得设置超时时间。

def _download_image(self, url, path):
 """下载单张照片"""
 try:
 resp = self.session.get(url, timeout=15)
 if resp.status_code == 200:
 open(path, 'wb').write(resp.content)
 except requests.exceptions.Timeout:
 logging.warning('get {} timeout'.format(url))
 except requests.exceptions.ConnectionError as e:
 logging.error(e.__str__)
 finally:
 pass

爬取测试

  • 爬取过程

capturing

  • 爬取结果

downloaded photos

写在最后

  1. 如果将请求参数中的format由jsonp改成json,则可以直接获取json数据
  2. 本用例并未使用多进程或多线程,所以速率不算快,还有待优化的地方

前段时间小编刷抖音的时候,刷到了咱们前端小伙伴制作的3D炫酷相册,居然那么火,细思一下,随着3D动画的普及,广泛的运作在各个平台,各官网都在实现3D页面。它可以更接近于真实的展示我们的产品和介绍,带来极强的视觉冲击感。所以说,为了让自己更加优秀,css3 3D动画必不可少。下面这篇文章,将带你初步了解CSS3实现酷炫的3D旋转透视




要想自己的网页能有3D特效,必须要会透视。

透视 perspective(基础问题,可以在我的推荐书籍中学习到)

  • 在2D平面产生近大远小视觉立体,但是只是效果二维的
  • 如果想在网页产生3D效果需要透视(理解成3D物体投影在2D平面内)。
  • 模拟人类的视觉位置,可认为安排一只眼睛去看
  • 透视我们也称为视距:视距就是人的眼睛到屏幕的距离
  • 距离视觉点越近的在电脑平面成像越大,越远成像越小
  • 透视的单位是像素


图片来源网络

正文:

  • CSS3 3D 转换的常用API介绍
  • CSS3 3D 应用场景
  • CSS3 3D 实现一个立方体
  • 1.CSS3 3D 转换的常用API介绍

    首先先上一张css 3D的坐标系:


    接下来我们来介绍几个常用的api:


    旋转

    • rotateX()
    • rotateY()
    • rotateZ() 以上几个api分别代表绕x,y,z轴旋转,如下例子为绕x轴旋转的例子:



    相关代码如下:

    <style>
    .d3-wrap {
     position: relative;
     width: 300px;
     height: 300px;
     margin: 120px auto;
     /* 规定如何在 3D 空间中呈现被嵌套的元素 */
     transform-style: preserve-3d;
     transform: rotateX(0) rotateY(45deg);
     transform-origin: 150px 150px 150px;
    }
    
    .rotateX {
     width: 200px;
     height: 200px;
     background-color: #06c;
     transition: transform 2s;
     animation: rotateX 6s infinite;
    }
    
    @keyframes rotateX {
     0% {
     transform: rotateX(0);
     }
     100% {
     transform: rotateX(360deg);
     } 
    }
    </style>
    <div class="d3-wrap">
     <div class="rotateX"></div>
    </div>
    复制代码

    位移(Transform)

    • translateX(x) 定义 3D 转化,仅使用用于 X 轴的值
    • translateY(y) 定义 3D 转化,仅使用用于 Y 轴的值
    • translateZ(z) 定义 3D 转化,仅使用用于 Z 轴的值 以上几个api分别代表相对x,y,z轴的位移,如下例子为向z轴位移的例子:


    这里我们需要注意的是为了能看出位移的效果,我们需要在父容器上加如下属性:


    .d3-wrap {
     transform-style: preserve-3d;
     perspective: 500;
     /* 设置元素被查看位置的视图 */
     -webkit-perspective: 500;
    }

    当为元素定义 perspective 属性时,其子元素会获得透视效果,而不是元素本身。 代码如下:

    .d3-wrap {
     position: relative;
     width: 300px;
     height: 300px;
     margin: 120px auto;
     transform-style: preserve-3d;
     perspective: 500;
     -webkit-perspective: 500;
     transform: rotateX(0) rotateY(45deg);
     transform-origin: center center;
    }
    
    .transformZ {
     width: 200px;
     height: 200px;
     background-color: #06c;
     transition: transform 2s;
     animation: transformZ 6s infinite;
    }
    
    @keyframes transformZ {
     0% {
     transform: translateZ(100px);
     }
     100% {
     transform: translateZ(0);
     } 
    }

    3D缩放

    • scaleX(x) 给定一个 X 轴的3D 缩放转换值
    • scaleY(x) 给定一个 Y 轴的3D 缩放转换值
    • scaleZ(x) 给定一个 Z 轴的3D 缩放转换值 缩放设置和上面的类似,这里就不做过多介绍了。

    理论上说以上三种常见变换已经够用了,值得关注的是我们要想让元素呈现出3D效果,以下不可忽视的API也很重要:


    2.CSS3 3D 应用场景

    css 3D主要应用在网站的交互和模型效果上,比如:

    • 3D轮播图
    • 3D产品介绍
    • 室内3D仿真
    • h5 3D活动页面,比较典型的就是某年淘宝的年终总结H5
    • 3D数据可视化成图
    • 3D模型图 其实如果css 3D用的熟悉了,一些基本的3D模型完全可以用css画出来。

    3.CSS3 3D 实现一个立方体


    核心思路就是用6个面去拼接,通过设置rotate和translate来调整相互之间的位置,如下:



    具体代码如下:

    .container {
     position: relative;
     width: 300px;
     height: 300px;
     margin: 120px auto;
     transform-style: preserve-3d;
     /* 为了让其更有立体效果 */
     transform: rotateX(-30deg) rotateY(45deg);
     transform-origin: 150px 150px 150px;
     animation: rotate 6s infinite;
    }
    .container .page {
     position: absolute;
     width: 300px;
     height: 300px;
     text-align: center;
     line-height: 300px;
     color: #fff;
     background-size: cover;
    }
    .container .page:first-child {
     background-image: url(./my.jpeg);
     background-color: rgba(0,0,0,.2);
    }
    .container .page:nth-child(2) {
     transform: rotateX(90deg);
     transform-origin: 0 0;
     transition: transform 10s;
     background-color: rgba(179, 15, 64, 0.6);
     background-image: url(./my2.jpeg);
    }
    
    .container .page:nth-child(3) {
     transform: translateZ(300px);
     background-color: rgba(22, 160, 137, 0.7);
     background-image: url(./my3.jpeg);
    }
    
    .container .page:nth-child(4) {
     transform: rotateX(-90deg);
     transform-origin: -300px 300px;
     background-color: rgba(210, 212, 56, 0.2);
     background-image: url(./my4.jpeg);
    }
    .container .page:nth-child(5) {
     transform: rotateY(-90deg);
     transform-origin: 0 0;
     background-color: rgba(201, 23, 23, 0.6);
     background-image: url(./my5.jpeg);
    }
    .container .page:nth-child(6) {
     transform: rotateY(-90deg) translateZ(-300px);
     transform-origin: 0 300px;
     background-color: rgba(16, 149, 182, 0.2);
     background-image: url(./my6.jpeg);
    }

    html结构

    <div class="container">
     <div class="page">A</div>
     <div class="page">B</div>
     <div class="page">C</div>
     <div class="page">D</div>
     <div class="page">E</div>
     <div class="page">F</div>
    </div>

    扩展

    我们可以基于上面介绍的,给父元素添加动画或者拖拽效果,这样就可以做成更有交互性的3D方块了,比如置骰子游戏vr场景3D相册等等,具体实现我会抽空依次总结出来,记得关注哦~





    作者:徐小夕_Lab实验室
    链接:https://juejin.im/post/5dd16b39f265da0bca78958e



    喜欢小编的可以点个赞关注小编哦,小编每天都会给大家分享文章。

    我自己是一名从事了多年的前端老程序员,小编为大家准备了新出的前端编程学习资料,免费分享给大家!

    如果你也想学习前端,那么帮忙转发一下然后再关注小编后私信【1】可以得到我整理的这些前端资料了(私信方法:点击我头像进我主页有个上面有个私信按钮)

    奥PicHome介绍

    这是一款基于 PHP + MySQL 的开源项目,选定本地电脑的图库目录之后,就能变成一个很漂亮的相册网页,并且可以通过分类、标签、颜色、链接、注释、时长、尺寸等参数检索内容,支持预览图片、视频、音频,甚至 txt 文档 。

    官方提供了一个演示站点:http://pichome.oaooa.com/

    可以轻松地放大缩小、翻转镜像查看,并且可以查看和下载原图,全凭之后可以通过左右键来浏览内容,可播放视频、音频,最有用的就是搜索功能了,找图快才用的爽。

    基于 PHP + MySQL 环境则可以部署在各种设备中,比如服务器、NAS、个人电脑、云服务器等,部署后可以在任何浏览器打开,所以手机电脑都可以方便的访问,最重要的是免费、开源,还是相当不错的。

    安装

    官方安装部署文档: https://www.yuque.com/pichome/install

    本次采用nginx+php7搭建

    Gitee下载 https://gitee.com/zyx0814/Pichome/releases

    下载安装包:笔者这边下载Pichome-beta3.3.tar.gz。

    github下载 https://github.com/zyx0814/Pichome/releases

    国内使用gitee地址
    https://gitee.com/zyx0814/Pichome/releases
    备用下载: http://js.funet8.com/centos_software/Pichome-beta3.3.tar.gz

    解压安装

    cd /data/wwwroot/web
    wget http://js.funet8.com/centos_software/Pichome-beta3.3.tar.gz
    tar -zxvf Pichome-beta3.3.tar.gz
    mv Pichome-beta3.3 p.xgss.net

    配置nginx

    nginx的配置

    server {
            listen 80;
        server_name p.xgss.net;
        root /data/wwwroot/web/p.xgss.net;
        access_log /data/wwwroot/log/p.xgss.net-access.log main_aliyun;
        error_log /dev/null;
    
        location / {
                index  index.php index.htm index.html;
                if (!-e $request_filename){
                            rewrite ^(.*)$ /index.php?s=$1 last;
                }
                
            }
            location ~ .*\.(php|php5)?$     {
                fastcgi_pass 127.0.0.1:7300;
                fastcgi_index index.php;
                fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
                include fastcgi_params;
            }
    
            location ~ .*\.(css|js|jpg|jpeg|gif|png|ico|bmp|gz|xml|zip|rar|swf|txt|xls|xlsx|flv|mid|doc|ppt|pdf|mp3|wma|exe)?$ {
                    expires max;
                    access_log off;
            }
    }
    

    域名解析到服务器

    配置站点

    访问: http://p.xgss.net/

    环境检查

    配置数据库

    新建数据库用户

    分配权限

    填写管理员信息

    新建库

    在线升级

    参考文档

    官网:https://oaooa.com/pichome.html

    开发者提供了 Windows、Linux 以及 Docker 安装方式。

    使用Billfish将图片导入站点

    使用Eagle或者Billfish,在本地windows系统下安装Billfish素材管理工具,billfish为免费的。

    在billfish软件中将照片分类

    将目录上传到服务器中,库设置中添加目录,就可以在web页面中显示你的图片了。