xx-Pixiv Spider

import requests
from lxml import etree
import json
import os
# 缺陷 1:下载的是图片合集,会下载其他角色的图片
# 缺陷 2:不能存 gif,因为P站的 gif 图片用的是我还不懂的方式
#================================================
#设置一个 Session 保持会话
se = requests.session()

#  E:\\0-Picture\\3-明日方舟\\鞭刃\\
#  E:\\0-Picture\\4-原神\\诺艾尔
#  ウィスラッシュ  鞭刃
#  ノエル Genshin  诺艾尔,原神
# 1000

class Pixiv():
    def __init__(self):
        # 登录界面的 URL
        self.base_url = 'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index'
        # 登录时 post 的对象
        self.login_url = 'https://accounts.pixiv.net/api/login?lang=zh'
        # P站首页
        self.main_url = 'http://www.pixiv.net'
        # 请求头
        self.headers = {
            'Referer': 'https://accounts.pixiv.net/login?lang=zh&source=pc&view_type=page&ref=wwwtop_accounts_index',
            "User-Agent": "Mozilla/5.0 (Windows NT 10.0; WOW64; rv:52.0) Gecko/20100101 Firefox/52.0",
            "Accept": "*/*",
            "Accept-Language": "zh-CN,zh;q=0.8,en-US;q=0.5,en;q=0.3",
            "Accept-Encoding": "",
            "Connection": "keep-alive",
        }
        self.pixiv_id = "xxxxxxxxxxxxxxxxxxxxxxx"
        self.password = "xxxxxxxxxxxxxxxxxxxxxx"

    def input_basic(self):
        raw = []
        # 输入 tag
        tag = input("请输入您想搜索的tag,若输入多个tag,请使用空格分割开:\n")
        tag = tag.replace(" ", "%20")
        raw.append(tag)
        # 输入 收藏数
        collect = input("请输入一个数,代码会筛选出收藏超过这个数值的图片:\n")
        collect = str(collect)
        raw.append(collect)
        if int(collect) < 0 or int(collect) > 10000:
            os.system('cls')
            print("Out of Range,ERROR")
            self.input_basic()
        # 创建目录
        path = input("请输入地址,若地址不存在,代码会在地址处创建一个文件夹\n")
        if (os.path.exists(path)) == False:
            os.mkdir(path)
        raw.append(path)
        return raw
        # if (os.path.exists("D:\\099_Picture\\明日方舟\\"+tag)) == False:
        #     os.mkdir("D:\\099_Picture\\明日方舟\\"+tag)

    #================================================
    # 这部分是用来登陆的
    def login(self):
        # 请求登录页面
        post_key_html = se.get(self.base_url, headers=self.headers).content.decode("utf-8")
        # 根据登录页面取得 post_key 里的 id
        post_key_parse = etree.HTML(post_key_html)
        post_key_value = post_key_parse.xpath("//input[@name='post_key']/@value")[0]
        print(post_key_value)
        # 登录用的 需要 post 的链接(先在浏览器登录一次,中间调转的时候能看到)
        login_url = 'https://accounts.pixiv.net/api/login?lang=zh'
        # post 所用的 data
        data = {
            'pixiv_id': self.pixiv_id,
            'password': self.password,
            'return_to': 'http://www.pixiv.net/',
            'post_key': post_key_value
            }
        # 使用 Session post后保持登录
        se.post(login_url, data=data, headers=self.headers)

    #=============================================================
    # 从网页数据的json字典文件里,提取图片网址列表和相关数据
    def get_pic_url_list(self, noelle_html_dic):
        noelle_ids = []
        # 读取字典里的 data
        noelle_data_list = noelle_html_dic['body']['illustManga']['data']
        for noelle_data in noelle_data_list:
            # 判断是否为gif图片
            # 如果是gif,则跳过
            if noelle_data['illustType'] ==2:
                continue
            else:
                noelle_id = []
                # 获取作品链接ID,放在 【noelle_id[0]】
                pic_id = noelle_data['id']
                noelle_id.append("https://www.pixiv.net/artworks/" + pic_id)
                # 获取作品图片链接,放在 【noelle_id[1]】
                pic_url = noelle_data['url']
                pic_url1 = pic_url.split("img/")[-1]
                pic_url2 = pic_url1.split("_p0")[0]
                pic_url = "https://i.pximg.net/img-original/img/"+pic_url2
                noelle_id.append(pic_url)
                # 获取作品图片数量,放在 【noelle_id[2]】
                pic_pageCount = noelle_data['pageCount']
                noelle_id.append(pic_pageCount)
                # 作品id,放在 【noelle_id[3]】
                noelle_id.append(pic_id)
                # 加入整体
                noelle_ids.append(noelle_id)
        print("已获得列表")
        return noelle_ids


    #=============================================================
    # 添加cookie后获取 t_p2 链接里的网页,结合cookie,获取网页里的字典
    def get_page(self, t_p2, cookie):
        p_headers = self.headers
        p_headers["cookie"] = cookie
        noelle_html = se.get(t_p2, headers=p_headers).content.decode("utf-8")
        print(noelle_html)
        noelle_html_dic = json.loads(noelle_html)
        noelle_ids = self.get_pic_url_list(noelle_html_dic)
        return noelle_ids
    #=============================================================
    # 网页url,循环1~50页
    def get_page_url(self, tag, collect):
        # 在获取的网页,输出方便检测
        t_p = "https://www.pixiv.net/ajax/search/artworks/" + tag + "?word=" + tag + "&order=date&mode=all&blt=" + collect + "&p=" + "1" + "&s_mode=s_tag&type=all&lang=zh"
        print(t_p)
        # cookie,没有cookie,网页获取就会出错
        cookie = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
        # 这个列表是储存了全部所需数据
        page_url_list = []
        # 循环,读取50页
        for i in range(1, 50):
            x = str(i)
            # t_p1 = "https://www.pixiv.net/tags/xxxxxxxxxxxxx/artworks?order=date&blt=100&p="+x+"&s_mode=s_tag"
            t_p2 = "https://www.pixiv.net/ajax/search/artworks/"+tag+"?word="+tag+"&order=date&mode=all&blt="+collect+"&p="+x+"&s_mode=s_tag&type=all&lang=zh"
            page_url = self.get_page(t_p2, cookie)
            # 如果为空,说明没有更多网页了结束了
            if page_url == []:
                print("第"+x+"页完成")
                break
            # 否则继续获取下一页
            else:
                print("第"+x+"页完成")
                page_url_list= page_url_list + page_url
        return page_url_list
    #=============================================================
    # 图片下载函数
    def download(self, path, page_url_list):
        # 下载出错的图片列表
        Wrong = []
        # headers 需要做一定修改,下方有解释
        d_headers = self.headers
        # 从列表里循环读取
        for page_url in page_url_list:
            # 没有图片所在网页的网址做 Referer 的话,图片会403
            d_headers['Referer'] = page_url[0]
            # page_url[2] :这网页上有多少张图片,和P站图片命名方式油关 xxxxx_p0.jpg
            for i in range(page_url[2]):
                # 组合出没有图片格式的图片网址
                url = page_url[1]+"_p" + str(i)
                # print(url)
                try:
                    # 组合出jpg格式的图片网址,图片有两种格式:jpg、png,这里穷举了两种格式,跳过了读取图片网页的过程
                    original = url+".jpg"
                    # 组合出图片名
                    pic_name = page_url[3]+"_p"+str(i)
                    # 获取 jpg 格式的图片
                    r = se.get(original, headers=self.headers, stream=True, timeout=5)
                    # 如果状态码为 200,说明 jpg 格式下载成功
                    if r.status_code == 200:
                        open(path + "\\" + pic_name + ".jpg", 'wb').write(r.content)  # 将内容写入图片
                        print(pic_name+" done")
                    # 如果状态码不是200,说明网页链接出错了,换成 png 格式试试
                    else:
                        original = url + ".png"
                        r = se.get(original, headers=self.headers, stream=True, timeout=5)
                        # 如果状态码是 200,那说明图片是 png 格式,存他
                        if r.status_code == 200:
                            open(path + "\\" + pic_name + ".jpg", 'wb').write(r.content)  # 将内容写入图片
                            print(pic_name+" done")
                        # 如果既不是 jpg,又不是 png
                        else:
                            Wrong.append(url)
                            print("图片:" + url + " 下载出错")
                    del r
                except:
                    print("图片:" + url + " 下载出错")
                    Wrong.append(url[0])
        return Wrong

    # =============================================================
    # 汇总
    def work(self):
        # 1、登录
        X = self.input_basic()
        tag = X[0]
        collect = X[1]
        path = X[2]
        self.login()
        # 2、获取文件列表
        p = self.get_page_url(tag, collect)
        print(p)
        print("一共"+str(len(p))+"个网页")
        a = input("是否开始下载?(Y/N)\n")
        if a == "Y" or a == "y" :
            # 下载
            self.download(path,p)
            print("over")
        else:
            print("over")

# 运行
pixiv=Pixiv()
a = pixiv.work()
print(a)
input("输入任意按键结束")

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值