python爬取知乎某个问题下所有图片

前言

  • 最近看知乎老是给我推荐‘有个xxx的女朋友是什么体验?’这种类似的钓鱼问题,索性就打开电脑开始撸代码爬图片。
  • 目标:把这个问题下所有回答下的图片下载到我的电脑。

1. 先来分析一下网页

1.1 打开问题网页

	`https://www.zhihu.com/question/285906324/answer/603575032`
  1. 这里提一下其实不用登陆知乎也能访问到问题的回答页面,也就说可以不用cookie.

2. 用谷歌浏览器打开后进入控制台抓一下包。(这个都会吧,不会的话百度一下教程很多。)

  • 2.1 寻找我们要的数据。

    • 寻找一番后,可以发现在下面这个请求中服务器返回了一个json格式的数据(很激动有木有!!!)。同时我们将这个请求的url作为scrapy的初始url.
      在这里插入图片描述
      是的!!!在这个json数据中包含了我们想要的一切数据。包括每一个回答的 1. html代码,以及2.回答人的用户名3.此回答的点赞数,评论数,以及4.此回答是否是最后一个回答。
  • 2.2 数据的位置找到了,下一步确定代码怎么写。

    • 图片url:这个在上一步的回答的html代码中,可以使用正则提取
    • 图片分组:根据用户名分组。
    • 筛选回答:毕竟不是每个回答下的都是。。。简单粗暴点,只下载点赞数大于500的。
    • 翻页操作:根据返回的数据判断是否是最后一个回答。

写代码

我用的是scrapy框架,其实用request也是可以的只是我最近在练习scray。

  1. 新建项目zhihu
    我默认你已经装好了scrapy,终端下输入:
    scrapy startproject zhihu
  2. 创建爬虫
    cd zhihu
    scrapy genspider zh zhihu.com
  3. 下面是代码部分
  4. zh.py
# -*- coding: utf-8 -*-
from copy import deepcopy

import scrapy
import json
import re
class ZhSpider(scrapy.Spider):
    name = 'zh'
    allowed_domains = ['zhihu.com']
    start_urls = ['https://www.zhihu.com/api/v4/questions/28046010/answers?include=data%5B*%5D.is_normal%2Cadmin_closed_comment%2Creward_info%2Cis_collapsed%2Cannotation_action%2Cannotation_detail%2Ccollapse_reason%2Cis_sticky%2Ccollapsed_by%2Csuggest_edit%2Ccomment_count%2Ccan_comment%2Ccontent%2Ceditable_content%2Cvoteup_count%2Creshipment_settings%2Ccomment_permission%2Ccreated_time%2Cupdated_time%2Creview_info%2Crelevant_info%2Cquestion%2Cexcerpt%2Crelationship.is_authorized%2Cis_author%2Cvoting%2Cis_thanked%2Cis_nothelp%2Cis_labeled%2Cis_recognized%2Cpaid_info%2Cpaid_info_content%3Bdata%5B*%5D.mark_infos%5B*%5D.url%3Bdata%5B*%5D.author.follower_count%2Cbadge%5B*%5D.topics&offset=&limit=3&sort_by=default&platform=desktop']

    def parse(self, response):
        print("新的一页!")
        dic = json.loads(response.text)
        # 此相应中的三个回答、
        answers_list = [answer for answer in dic.get('data') if answer.get('voteup_count') > 500]

        for answer in answers_list:
            item={}
            item['voteup_count'] = answer.get('voteup_count')
            author = answer.get('author').get('name')
            item['author'] = author
            answer_html_content = answer.get('content')
            # 正则选出回答中的img url
            incomplete_urls = re.findall(r'https:\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:/~\+#]*[\w\-\@?^=%&/~\+#])?',answer_html_content)

            # 使用集合去除重复
            img_urls = set([later_url for _, later_url in incomplete_urls])
            for img_url in img_urls:
                if img_url[-5] == 'r':
                    item["url"] = 'https://pic3.zhimg.com' + img_url
                    yield deepcopy(item)

        if not dic.get('paging').get('is_end'):
            next_url = dic.get('paging').get('next')
            yield scrapy.Request(
                next_url,
                callback=self.parse
            )
  1. 在settings.py的大约70行左右修改如下:
# 这段代码的作用是使用scray自带的下载图片的项目管道。除了这个方法也是可以使用requests模块实现的
ITEM_PIPELINES = {
    'zhihu.pipelines.ZhihuPipeline': 300,
    'scrapy.contrib.pipeline.images.ImagesPipeline': None,
    # 如果需要采用自定义的ImagesPipiline,需要将自带的ImagesPipelin设置为None
    'zhihu.pipelines.ImagesPipiline': 1

}  
# 配置图片的保存目录
IMAGES_STORE = 'images'
# 在ImagesPipeline进行下载图片时,配置图片对应的Item字段
IMAGES_URLS_FIELD = 'img_url 
  1. 在piplines.py中添加itempipelines
# -*- coding: utf-8 -*-

# Define your item pipelines here
#
# Don't forget to add your pipeline to the ITEM_PIPELINES setting
# See: https://docs.scrapy.org/en/latest/topics/item-pipeline.html


from scrapy.pipelines.images import ImagesPipeline
from scrapy.http import Request

class ZhihuPipeline(object):
    def process_item(self, item, spider):
        return item


class ImagesPipiline(ImagesPipeline):
    def get_media_requests(self, item, info):
        # 从item中获取要下载的图片的url,根据url构造Request()对象,并返回该对象
        image_url = item['url']
        yield Request(image_url, meta={'item': item})

    def file_path(self, request, response=None, info=None):
        # 用来自定义图片的下载路径
        item = request.meta['item']

        path = item.get('author')+ '/' + item.get("url")[28:]
        #path = item.get("url")[28:]
        return path

    def item_completed(self, results, item, info):
        # 图片下载完成后,返回结果result
        print(results)
        print("点赞数:{}".format(item.get('voteup_count')))
        return item

展示一下结果在这里插入图片描述

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值