---
layout: post
title: "Pixiv 爬虫"
subtitle: "教学任务-啊~萌妹子~"
date: 2016-09-13
author: "Elico"
header-img: "img/01-bg.jpg"
tags:
- 爬虫
---

基于python的爬虫有很多种，用到的库也多种多样，这里用[Pixiv插画月排行](http://www.pixiv.net/ranking.php?mode=monthly&content=illust)做一下试验。

比较简单的有利用selenium模拟浏览器行为，它会启动浏览器驱动，但是这样会额外耗费资源启动浏览器，而且打开新的窗口比较烦，虽然可以用PhantomJS替代（PhantomJS是将网页内容读进内存，不会打开新窗口）。但是Pixiv的排行有图片延迟加载，一个笨办法是用js控制滚动条，但是这样太不优雅了（本来打开新窗口就不优雅...），所以我们用另一种方法。 

主要用到的库：urllib、urllib2、cookielib、json、beautifulsoup4等。

首先分析网站pixiv插画月排行，利用Chrome的开发者模式可以分析网站请求：F12（打开JS控制台）- Network - Clear - 拖动网站滚动条，在XHR可以发现请求
![01.jpg](/img/pixivSpider/01.jpg)
![02.jpg](/img/pixivSpider/02.jpg)
可以发现里面有排行图片的当前排名、插画id、插画名、插画缩略图链接、画师id、昵称等。但是这里没有原图链接，这里我们用一个取巧的方法，直接提交<font color = "#3399ff">www.pixiv.net/member_illust.php?mode=medium&illust_id= + 插画id</font>访问插画首页。 

我们随便打开一个上述插画页面，查看网页源代码，发现当试图访问原图片的时候，如果没有登录会转到登录页面，我们先登录看一下原图链接的标签：class = “original-image”，data-src里就是原图链接。如果是漫画需要修改上述链接的medium为manga，源码的标签为data-filter=“manga-image”，原图链接仍然是data-src里的内容。 

这基本上就是所有的分析内容（然而下面还有坑）。 
我们把问题理一下： 
* 获取插画首页
* 解决登陆问题 
* 获取原图链接 
* 优化下载速度（可选）

### 获取插画首页
***
通过上面的分析，这个问题应该已经解决掉了，直接访问<font color="#3399ff">http://www.pixiv.net/ranking.php?mode=monthly&content=illust&p=页号&format=json</font>请求json数据就可以了。

### 解决登录问题
***
在主站登录页面随便登录一下抓包可以看到这样的post：

![03.jpg](/img/pixivSpider/03.jpg)

这个就是cookie的格式了，post_key可以查看源代码看到，每次访问这个页面会随机收到一个。 

改版前是没有post_key的，现在好像还会经过多次跳转，也用人会利用这个接口<font color="#3399ff">www.secure.pixiv.net/login.php</font>，我找到一个更方便的接口，按如下格式填写即可：

```python
def __loginRequest(self):
        cookie = cookielib.MozillaCookieJar("cookie.txt")
        self.__opener = urllib2.build_opener(urllib2.HTTPCookieProcessor(cookie))
        header = {
            "Accept-Language": "zh-CN,zh;q=0.8",
            'Referer': 'https://www.pixiv.net/login.php?return_to=0',
            "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
        }
        loginInfo = urllib.urlencode({
            'mode': 'login',
            'pass': 'password',#your password
            'pixiv_id': 'username',#your username
        })
        loginUrl = "https://www.pixiv.net/login.php"
        request = urllib2.Request(loginUrl, data=loginInfo, headers=header)
        self.__opener.open(request)
        cookie.save(ignore_discard = True, ignore_expires = True)
```

### 获取原图链接
***
对页面的随便html分析一下就可以了，我用的库是BeautifulSoup4，也可以用正则表达式，方法很多。

但是当我们想通过链接下载时会发现403错误，这就是之前提过的坑，随便打开一张图的高清页抓包看一下：
![04.jpg](/img/pixivSpider/04.jpg)
原来网站还要验证访客是从哪个页面条转过来的，按这个格式把这个这个referer加进header就可以了：

```python
def __DownloadRequest(self, refererUrl, originalUrl):
        header = {
            "Accept-Language": "zh-CN,zh;q=0.8",
            "User-Agent": "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/52.0.2743.116 Safari/537.36"
        }
        header['referer'] = refererUrl
        request = urllib2.Request(originalUrl, headers=header)
        return self.__opener.open(request).read()
```

### 优化下载速度（可选）
***
网络资源可能不能得到充分利用，例如我在实验室是百兆网，但是下载速度只有可怜的130k/s。（实际上后来发现那个路由器的信号也不好，影响了速度）
这里就不贴具体的代码了，思路就是开多线程或多进程，应该不难实现。

最后写了个简单的html浏览图片：
![05.jpg](/img/pixivSpider/05.jpg)
这个博客是之前写的，发布在了我的csdn博客...
实现代码放在了[这里](https://github.com/elicococoo/BlogCodeStorage/tree/master/PixivSpider)