之前的爬虫采取的方案都是直接进入网页再用正则获取实际的图片地址,这样的做法看上去很好,但是在获取网页的时候需要下载整个网页,所以每次越有80%的内容是重复的,而且剩下的20%中我们需要的又只是5%。同时过高的访问频率还可能导致目标站点将自己拉近黑名单。所以我们需要一种能够直接提供我们需要信息的方法。

这时候API就显得十分重要,API能够直接根据参数提供我们想要的实体,而不是写入整张网页中,能有效的节约编写解析代码的时间,也能减轻服务器的压力。

还是以konachan为例,konachan官方直接提供了一个API(API文档),查看文档的Posts部分

http://konachan.com/post.json

我们可以发现konachan提供json接口,同时支持参数:

  • page

  • tag

limit

这样就可以节约大量在页面解析方面的时间

编写代码

requests代理

由于站内有部分河蟹内容,所以部分地区可能无法直接连接(比如我),所以在运行此python程序的时候需要使用代理访问。ss-qt5可以直接将ss在本地转为http协议,在使用的时候就非常方便,如果你的ss客户端无法将sock5转为http则可以使用Privoxy等软件转换一下;

import requests
proxies = { "http": "http://127.0.0.1:1080" }
url=r'http://konachan.com/post.json?page=1&limit=50'
html = requests.get(url, proxies=proxies)

这样requests就可以从代理获取目标网页

解析json

可以看到获得的结果为一大串的json,所以要将内容转化为python的json对象,这样才能提取到我们要的内容

先对json内容进行分析得到,由于参数太多了,这次就先对其中比较重要的内容进行提取

tags=[]
ids=[]
file_sizes=[]
file_urls=[]
widths=[]
heights=[]
jsons=html.json()#得到json数组
for tmp in jsons:#根据key提取,并将所有value放入数组内
    tags.append(tmp['tags'])
    ids.append(tmp['id'])
    widths.append(tmp['width'])
    heights.append(tmp['height'])
    file_sizes.append(tmp['file_size'])
    file_urls.append(tmp['file_url'])

下载图片

这是跟直接从konachan下载图片一样,是id+tags+ext组成文件名,可以根据自己需求修改

      for i in range(0, len(file_urls) - 1):#循环至有效长度
        try:
            tmps = file_urls[i].split(".")#分割url
            tags[i]=tags[i].replace("/","-")#替换tags里的“/”防止创建文件时出错
            if len(tags[i]) > 140:#对过长的文件名进行分割
                fileName = path + "/" + str(ids[i]) + tags[i][0:100] + "." + tmps[len(tmps) - 1]
            else:
                fileName = path + "/" + str(ids[i]) + tags[i] + "." + tmps[len(tmps) - 1]
            print("开始下载:"+fileName+"\n")
#通过代理下载图片
            r = requests.get("http:" + file_urls[i], stream=True, proxies=proxies)
#以缓存方式写入硬盘(不过python好像默认是使用缓冲区的?)
            with open(fileName, 'wb') as f:
                for chunk in r.iter_content(chunk_size=1024):
                    if chunk:
                        f.write(chunk)
                        f.flush()
                f.close()
            print("下载结束\n")
        except:
            print(ids[i]+" : failed")

这样一个基础的爬虫就写好了