最近在极客时间上学习数据分析的内容,刚好老师在课程上讲了爬虫的内容,而且是爬取豆瓣上的图片,把老师给的代码稍微修改了一下,再加上了我的理解和说明。
Win10 系统下 Python3,编译器是 PyCharm 。json、re 和 os 是不用辛苦安装;requests 可以直接用 pip install requests 安装。要是不知道该怎么安装,那还是用 Pycharm 安装吧。
代码不算多,为了能解释清楚,所以是按顺序分开来,用的时候按顺序复制就好。
先导入要用的库
import json
import re
import os
import requests
query 是查询,在代码里的意思是想要爬取的人的名字,随意修改。
path 这个是可以随意修改的,可以把 path = os.getcwd()
这一句取消注释,然后注释掉下面那一句。path = os.getcwd()
的作用是获得当前文件的路径,然后把这个 .py 文件的路径赋值给 path。
path = 'C:/Users/ASUS/Desktop/测试'
的意思是一样的,把后面这个路径赋给 path,如果用这个的话,记得修改成自己想要的路径。两个语句只能选择一个,另一个需要注释掉。
picpath 就是图片所在的目录,接下来就是要判断一下这个目录是否创建了,如果没有创建,那就创建。
query = '王祖贤'
path = os.getcwd() # 当前路径,可以替换成别的路径
# path = 'C:/Users/ASUS/Desktop/测试'
picpath = path + '/' + query # 设置的图片目录
print(picpath) # 输出设置的图片目录
if not os.path.isdir(picpath): # 如果图片目录未创建则创建一个
os.mkdir(picpath)
这里是下载图片的 download 函数,传入的 src 是图片的链接,传入的 id 是图片的名称,图片的完整名就是图片对应的 id 再加上 .jpg。
dir 就是图片的路径,先是请求图片,如果遇到网络问题导致请求不到,那么就捕获 requests 的 ConnectionError 异常。如果能够请求到,那就打开以 wb 也就是二进制写模式打开图片,图片的路径就是上面说到的dir 。打开之后就把请求到的图片的内容写入,然后关闭。
def download(src, id):
dir = picpath + '/' + str(id) + '.jpg'
try:
pic = requests.get(src, timeout=10)
except requests.exceptions.ConnectionError:
print(id + ' 图片无法下载')
fp = open(dir, 'wb')
fp.write(pic.content)
fp.close()
下面这里就是进入循环,请求 url,找到这个 url 还是挺简单的。先进入下面给出的链接,然后 F12 打开开发者工具,点击 Newwork,然后再点击 XHR(XMLHttpRequest),接着 F5 刷新一下页面就能看到 search_photo?q= 那一串东西,点击它,接着去点击一下 Headers,最后就能看到 Request URL。
https://www.douban.com/search?cat=1025&q=王祖贤
把 Request URL 的链接打开,就能看见 JSON 格式的数据了。当然,不出意外的话,你看到的是下图这种看得令人难受的样子。
如果用谷歌浏览器的扩展程序 JSONView 的话,你看到的是下图这种清爽的样子,清晰明了又好看。
多试几次就能发现 Request URL 的规律了,start=0,start=20,start=40.
拉到最底下你就能看到 total: 22598,limit: 20,more: true 这样的数据,意思是一共有 22598 张图片,一次只能请求 20,more 表示后面的还能请求。不过实际测试中我发现 start=2001 就显示 total: -1,limit: 20,more: false。
for i in range(0, 22471, 20) 的意思是从 0 开始循环到 22471,步长或者说间隔是 20,意思是 i 的值的变换规律是 0,20,40 ,60。
url 就是每一次请求的链接,得到的结果赋值给 html,接着把 JSON 对象的 html 转换成 Python 对象,接着是用一个 for 循环把每一个图片对应的链接和 id 拿到,然后交给前面说到的下载函数进行下载。
有一点需要注意,我把图片链接中的 thumb 全部替换成了 l,因为测试的时候发现替换之后的图片是大图,试试下面这个链接就知道了。
https://img3.doubanio.com/view/photo/thumb/public/p611792033.jpg
这里实现替换可以用两种方法,一种是直接 replace,一种是用 re 模块的 sub 方法
''' for 循环 请求全部的 url '''
for i in range(0, 22471, 20): #
url = 'https://www.douban.com/j/search_photo?q=' + query + '&limit=20&start=' + str(i)
html = requests.get(url).text # 得到返回结果
response = json.loads(html, encoding='utf-8') # 将 JSON 格式转换成 Python 对象
print('已下载 ' + str(i) + ' 张图片')
for image in response['images']:
image['src'] = image['src'].replace('thumb', 'l')
# image['src'] = re.sub(r'thumb', r'l', image['src'])
print(image['src']) # 查看当前下载的图片网址
download(image['src'], image['id']) # 下载一张图片
在写好的路径下出现一个王祖贤的文件夹,文件夹里面有一堆图片。我这里的路径是 C:/Users/ASUS/Desktop/测试/王祖贤 ,搞定收工。
题图:Photo by Bart LaRue on Unsplash