爬虫实例——爬取淘女郎的相册(通过谷歌浏览器的开发者工具找出规律快速爬取)
Posted 昨、夜星辰
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了爬虫实例——爬取淘女郎的相册(通过谷歌浏览器的开发者工具找出规律快速爬取)相关的知识,希望对你有一定的参考价值。
用正常的方式(selenium、PhantomJS、BeautifulSoup)爬取淘女郎相册不仅困难,效率很低,而且很容易卡死。
我借助谷歌浏览器的开发者工具找出每个页面的规律,快速获取每张照片的链接,再下载,这样效率就很高了。
过程
首页很简单,没有采用JS渲染,直接用requests就能获取完整的源代码,没什么说的。
淘女郎首页采用了JS渲染,直接用requests是获取不到完整的源代码的,此时可以打开谷歌浏览器的开发者工具,主要看“Network”,筛选出“XHR”,如下图:
从上图可知,从这个页面可以获取淘女郎的个人资料,读者可以直接从浏览器中打开该链接,看看是否能获取淘女郎的个人资料。
https://mm.taobao.com/self/info/model_info_show.htm?user_id=687471686
观察这个URL很容易发现,我们只需改变用户ID就可以得到不同淘女郎的个人资料了,所以在爬取首页时记得把用户ID也爬取下来。
接下来看一下相册,打开淘女郎的相册,同样是打开谷歌浏览器的开发者工具,看“XHR”,你可以得到这么一个链接:
https://mm.taobao.com/self/album/open_album_list.htm?_charset=utf-8&user_id%20=687471686
从这个链接你可以获取淘女郎的相册链接、名称和照片数,但得到的只是第一页的数据,怎么看第二页的呢,在前台翻页后从开发者工具可以看到多了一个XHR:
https://mm.taobao.com/self/album/open_album_list.htm?_charset=utf-8&user_id%20=687471686&page=2
这就是相册的规律,通过两个参数控制,一个是用户ID,一个是页数。
接下来看看相册里面的内容,此时看XHR得不到我们要的内容,应该看看别的,我在JS里发现了这个页面:
从上图可知,这个页面会返回JSON数据,里面包含了图片的链接,但通过查找发现只有16张照片,实际上这个相册却有45张照片,回到前台,下拉滚动条,发现多了几个这样的页面:
它们的URL分别是:
https://mm.taobao.com/album/json/get_album_photo_list.htm?user_id=687471686&album_id=10000702574&top_pic_id=0&cover=%2F%2Fimg.alicdn.com%2Fimgextra%2Fi2%2F687471686%2FTB1TlwDLFXXXXbxaXXXXXXXXXXX_!!2-tstar.png&page=1&_ksTS=1465185952899_155&callback=jsonp156
https://mm.taobao.com/album/json/get_album_photo_list.htm?user_id=687471686&album_id=10000702574&top_pic_id=0&cover=%2F%2Fimg.alicdn.com%2Fimgextra%2Fi2%2F687471686%2FTB1TlwDLFXXXXbxaXXXXXXXXXXX_!!2-tstar.png&page=2&_ksTS=1465186271282_254&callback=jsonp255
https://mm.taobao.com/album/json/get_album_photo_list.htm?user_id=687471686&album_id=10000702574&top_pic_id=0&cover=%2F%2Fimg.alicdn.com%2Fimgextra%2Fi2%2F687471686%2FTB1TlwDLFXXXXbxaXXXXXXXXXXX_!!2-tstar.png&page=3&_ksTS=1465186273660_330&callback=jsonp331
每个URL包含的参数都很多,有两个参数(_ksTS和callback)看不出规律,于是我打开了另一个相册,发现每个相册的这两个参数都是固定的,第一页的都是155-156,第二页的都是254-255,第三页的都是330-331,且从第二页开始,下一页的callback减去上一页的callback都等于76。
然而知道这些规律后我发现并没什么卵用,因为我发现即使没有这些参数也能获取数据:
https://mm.taobao.com/album/json/get_album_photo_list.htm?user_id=687471686&album_id=10000702574&page=1
https://mm.taobao.com/album/json/get_album_photo_list.htm?user_id=687471686&album_id=10000702574&page=2
https://mm.taobao.com/album/json/get_album_photo_list.htm?user_id=687471686&album_id=10000702574&page=3
其实只需用户ID、相册ID和页数即可。
接下来就是获取每张照片的URL和保存照片了。
代码
# -*- coding: utf-8 -*- import sys reload(sys) sys.setdefaultencoding(\'utf-8\') \'\'\' 作者:昨夜星辰 注意事项:该脚本只能在Linux环境用Python 2.x运行,如需在其他环境运行请读者自行修改。 \'\'\' import re import os import shutil import requests from bs4 import BeautifulSoup # 创建文件夹,若已存在则删除,再创建。 def create_folder(path): if os.path.exists(path): if os.path.isdir(path): shutil.rmtree(path) else: os.remove(path) os.mkdir(path) # 询问用户 def ask_user(string): while True: answer = raw_input(string) if answer == \'Y\': return True elif answer == \'N\': return False else: print \'输入有误,请重新输入!\' # 创建根目录 root_folder = \'淘女郎\' create_folder(root_folder) # 遍历每位淘女郎 url = \'https://mm.taobao.com/json/request_top_list.htm?page=1\' bs1 = BeautifulSoup(requests.get(url).text, \'lxml\') for top in bs1(\'p\', \'top\'): name = top.find(\'a\').text age = top.find(\'em\').text city = top.find(\'span\').text user_id = top.find(\'span\', \'friend-follow J_FriendFollow\')[\'data-userid\'] print \'发现一位美眉,她叫做%s,今年%s,住在%s,现在开始爬取她的个人页面……\' % (name, age, city) # 以淘女郎的昵称新建文件夹 mm_folder = \'%s/%s\' % (root_folder, name) create_folder(mm_folder) # 获取淘女郎的个人资料并保存到文件 url = \'https://mm.taobao.com/self/info/model_info_show.htm?user_id=\' + user_id bs2 = BeautifulSoup(requests.get(url).text, \'lxml\') base_info = bs2.find(\'ul\', \'mm-p-info-cell clearfix\') info_list = base_info(\'span\') result = [] result.append(\'昵称:\' + info_list[0].text) result.append(\'生日:\' + info_list[1].text.strip()) result.append(\'所在城市:\' + info_list[2].text) result.append(\'职业:\' + info_list[3].text) result.append(\'血型:\' + info_list[4].text) result.append(\'学校/专业:\' + info_list[5].text) result.append(\'风格:\' + info_list[6].text) result.append(\'身高:\' + base_info.find(\'li\', \'mm-p-small-cell mm-p-height\').find(\'p\').text) result.append(\'体重:\' + base_info.find(\'li\', \'mm-p-small-cell mm-p-weight\').find(\'p\').text) result.append(\'三围:\' + base_info.find(\'li\', \'mm-p-small-cell mm-p-size\').find(\'p\').text) result.append(\'罩杯:\' + base_info.find(\'li\', \'mm-p-small-cell mm-p-bar\').find(\'p\').text) result.append(\'鞋码:\' + base_info.find(\'li\', \'mm-p-small-cell mm-p-shose\').find(\'p\').text) print \'资料收集完毕,正在保存她的个人资料……\', filename = \'%s/%s.txt\' % (mm_folder, name) with open(filename, \'w\') as f: f.write(\'\\r\\n\'.join(result)) print \'保存完毕!\' # 获取相册的总页数 url = \'https://mm.taobao.com/self/album/open_album_list.htm?_charset=utf-8&user_id%20=\' + user_id bs3 = BeautifulSoup(requests.get(url).text, \'lxml\') album_total_page = int(bs3.find(\'input\', id=\'J_Totalpage\')[\'value\']) # 遍历每一页 for album_page in range(1, album_total_page + 1): url = \'https://mm.taobao.com/self/album/open_album_list.htm?_charset=utf-8&user_id%%20=%s&page=%d\' % (user_id, album_page) bs3 = BeautifulSoup(requests.get(url).text, \'lxml\') album_count = 1 # 遍历每一个相册 for album_area in bs3(\'div\', \'mm-photo-cell-middle\'): # 获取相册的链接、id、名称和照片数 album_url = \'https:\' + album_area.find(\'h4\').find(\'a\')[\'href\'] album_id = re.search(r\'album_id=(\\d+)\', album_url).group(1) album_name = album_area.find(\'h4\').find(\'a\').text.strip() pic_num = album_area.find(\'span\', \'mm-pic-number\').text pic_num = re.search(r\'\\d+\', pic_num).group(0) print \'现在开始爬取她的第%d个相册,相册名为:《%s》(%s张)……\' % (album_count, album_name, pic_num) # 根据照片数计算总页数 total_page = int(pic_num) / 16 + 1 # 以相册名新建文件夹 album_folder = \'%s/%s\' % (mm_folder, album_name) create_folder(album_folder) pic_count = 1 # 遍历每一页 for page in range(1, total_page + 1): url = \'https://mm.taobao.com/album/json/get_album_photo_list.htm?user_id=%s&album_id=%s&page=%s\' % (user_id, album_id, page) json = requests.get(url).json() for pic in json[\'picList\']: print \'现在开始下载该相册的第%d张照片……\' % pic_count, pic_url = \'https:\' + pic[\'picUrl\'] pic_url = re.sub(r\'290\', \'620\', pic_url) filename = \'%s/%s.jpg\' % (album_folder, pic_count) with open(filename, \'wb\') as f: f.write(requests.get(pic_url).content) print \'下载完毕!\' pic_count += 1 if ask_user(\'该相册已经下载完毕,是否下载下一个相册?(Y/N)\') == False: break album_count += 1 if ask_user(\'当前页的相册已经下载完毕,是否下载下一页?(Y/N)\') == False: break
以上是关于爬虫实例——爬取淘女郎的相册(通过谷歌浏览器的开发者工具找出规律快速爬取)的主要内容,如果未能解决你的问题,请参考以下文章
爬虫实例——爬取1元夺宝用户头像(借助谷歌浏览器开发者工具)
爬虫实例——爬取煎蛋网OOXX频道(反反爬虫——伪装成浏览器)
Python 爬虫篇 - 通过urllib.request伪装成浏览器绕过反爬虫爬取网页所有连接实例演示,urllib2库的安装