Python爬虫之Pixiv

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/insthink/article/details/51272773

   正在学习Python,想想需要实践检验理论,于是想到爬点东西。作为宇宙纯种动漫宅,对于插画的热爱无人可挡,于是就把目标锁定在了大名鼎鼎的p站,主站地址:http://www.pixiv.net/

    目标:得到进入日榜的插画,自动保存图片及相关信息。

    PS:该帖用来记录基本流程,以及在实践过程中遇到的一些问题和解决思路;爬取得到的图片自己欣赏即可,请不要随意上传,更不要用于商业用途,尊重画师的劳动成果!

——————————————————————————————————————————

设计一个Pixiv类

class Pixiv:


一、初始化

    def __init__(self):
        # 请求报文需要的一些信息
        # 登陆地址
        self.loginURL = 'https://www.pixiv.net/login.php'
        # 头部信息
        self.loginHeader = {
            'Host': "www.pixiv.net",
            'User-Agent': "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/" +
                          "537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36",
            'Referer': "http://www.pixiv.net/",
            'Content-Type': "application/x-www-form-urlencoded",
            'Connection': "keep-alive"
        }
        # 包括用户名、密码等表单信息
        self.postData = urllib.urlencode({
            'mode': 'login',
            'return_to': '/',
            'pixiv_id': '[email protected]',
            'pass': '********',
            'skip': '1'})
        # cookie信息,服务器用来识别用户身份
        # 获取本地cookie信息,构建一个包含cookie信息的opener
        self.cookie = cookielib.LWPCookieJar()
        self.cookieHandler = urllib2.HTTPCookieProcessor(self.cookie)
        self.opener = urllib2.build_opener(self.cookieHandler)


二、模拟登陆

扫描二维码关注公众号,回复: 3798549 查看本文章

    def get_first_page(self):
        # 向服务器发起请求,请求报文内容包括:URL,头部,表单;请求方式为post
        request = urllib2.Request(self.loginURL, self.postData, self.loginHeader)
        # 用我们新建的包含cookie信息的opener打开,并返回服务器响应报文
        response = self.opener.open(request)
        # 内容读取,并以UTF-8解码
        content = response.read().decode('utf-8')
        print u'响应代码:%s' % response.getcode()
        return content

三、排行榜信息获取

    def get_rank_list(self):
        # 进入dailyRank界面
        rank_url = 'http://www.pixiv.net/ranking.php?mode=daily&content=illust'
        request = urllib2.Request(rank_url)
        response = self.opener.open(request)
        content = response.read().decode('UTF-8')
        print response.getcode()
        # 利用正则表达式,找到dailyRank界面内的作品信息(可以保存为.txt说明用)
        pattern = re.compile('<section.*?data-rank-text="(.*?)" data-title="(.*?)" ' +
                             'data-user-name="(.*?)" data-date="(.*?)".*?data-id="(.*?)"', re.S)
        # findall返回一个包含5元组的列表
        items = re.findall(pattern, content)
        # 可以打印出来看看
        # for item in items:
        #      print item[0], item[1], item[2], item[3], item[4]
        print u"已经获得排名、名称、作者、时间、ID信息O(∩_∩)O哈!"
        return items


四、每幅图片所在页面的地址获取

    def get_img_page(self):
        # 每幅图片所在页面地址 = 基地址 + 图片id(这是作者的图片展示地址)
        base_url = 'http://www.pixiv.net/member_illust.php?mode=medium&illust_id='
        # 从rank界面获取到的id信息派上用场了
        illust_id = [item[4] for item in self.get_rank_list()]
        # 用一个列表存储所有的页面地址
        img_pages = [base_url + str(i) for i in illust_id]
        return img_pages


五、图片地址获取

    def get_img_urls(self, img_pages):
        # 存储所有图片url的列表
        img_urls = []
        # 遍历所有illust_id界面,前100名
        for index, url in enumerate(img_pages[:100]):
            print u"正在进入第%d名插画界面" % (index + 1)
            request = urllib2.Request(url)
            response = self.opener.open(request)
            content = response.read().decode('UTF-8')
            # 查找原画地址,不同浏览器获得的HTML有差异,以CHROME为准
            # 插画的话,直接获得原图;如果是漫画,则获取缩略图
            try:
                pattern = re.compile('<img alt.*?data-src="(.*?)"', re.S)
                img = re.search(pattern, content)
                print img.group(1)
            except AttributeError:
                pattern = re.compile('<div class="multiple.*?src="(.*?)"', re.S)
                img = re.search(pattern, content)
                print img.group(1)
            img_urls.append(img.group(1))
        return img_urls

六、创建保存目录

    def make_dir(self):
        # 获取格式化时间,提取年月日作为目录名称
        y_m_d = time.localtime()
        path = 'D:/%s_%s_%s' % (str(y_m_d[0]), str(y_m_d[1]), str(y_m_d[2]))
        is_exist = os.path.exists(path)
        if not is_exist:
            os.makedirs(path)
            print u"创建目录成功!"
            return path
        else:
            print u"目录已经存在!"
            return path

七、保存图片

    def save_img_data(self, urls, pages, path):
        for i, img_url in enumerate(urls):
            filename = path + '/' + str(i) + '.jpg'
            # 里面的Referer很重要哦,不然服务器会拒绝访问,也就获取不到原图数据
            # 之前没有管Referer,直接抛给我403
            # 服务器会检查Referer,来判断是否对这个请求做响应;我们要尽可能模仿正常上网行为。
            # 这里的Referer就是我们之前获取到的页面地址
            img_headers = {
                'Referer': pages[i],
                'User-Agent': "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/" +
                              "537.36 (KHTML, like Gecko) Chrome/50.0.2661.87 Safari/537.36"}
            img_request = urllib2.Request(img_url, headers=img_headers)
            img_response = self.opener.open(img_request)
            print img_response.getcode()
            data = img_response.read()
            # input = raw_input()
            # 保存图片到指定目录
            if img_response.getcode() == 200:
                with open(filename, 'wb') as f:
                    f.write(data)
                    print u"保存第%d张图片中" % i


八、保存图片相关信息

    def save_info(self, items, path):
        # 记录前100名的信息
        filename = path + '/info.txt'
        infos = u'前100名信息:\n'
        for item in items[:100]:
            infos += u'-----------第%s------------\n' % item[0]
            infos += u'Name:%s\nAuthor:%s\nID:%s\n' % (item[1], item[2], item[4])
        with open(filename, 'w') as f:
            f.write(infos.encode('UTF-8'))


——————————————————————————————————————————

下一篇(续)会贴上完整代码(还有好多地方可以改进!!)


猜你喜欢

转载自blog.csdn.net/insthink/article/details/51272773