taomm
May 24
python , 爬虫
Word Count: 1.4k(words)
Read Count: 6(minutes)
python爬虫实战(三):爬取淘女郎图片
引言
爬取淘女郎图片是为了给一个朋友找找穿衣的搭配,但是期间遇到了很多问题,所以就写了这篇文章记录一下解决方案。
分析
我们要爬取的网页是:淘女郎 ,通过分析可以看到每个淘女郎的主页:
)
随便找一个淘女郎的个人主页,有大量的图片,而且几乎没有多余的无关图片,所以直接用正则表达式可以轻易提取出图片的原始链接
那么我们爬完第一页,就要翻页了,尝试点击了一下“第二页”,网址竟然没变?!看来有麻烦了:翻页操作使用的是ajax异步加载的!那么我们的主要问题就是取解决如何获取ajax异步加载的内容了
爬取异步加载内容
方法一
使用selenium+phantomjs模拟点击操作,然后异步内容加载完成后直接从html中提取内容。
这个方法比较简单,主要涉及的就是两个程序的使用。
这里不详细讲了,之后会再涉及到的~
方法二
直接获取ajax返回的内容,从中分析出淘女郎的个人主页地址。
首先我们要获取ajax请求的地址。我们尝试点击“下一页”,很容易就找到了这个请求:
其中,form data中是筛选器中填写的内容,这里我没有调整筛选器,所以大部分都是默认,或者为空。currentPage就很明显了,代表请求的页数,这样根据地址,就可以直接获取异步加载的内容了。
查看一下Response的内容:
资料还挺全的~
那么搜索一下,看看从哪里可以找到“宴宴gy”这个人的个人主页地址:
先到浏览器点看“宴宴gy”的个人主页,把地址复制下来,再到Response中搜索
但是,,,竟然没有搜索到!
因为既然我们可以跳转到某个人的个人主页(https://mm.taobao.com/self/aiShow.htm?spm=719.7763510.1998643336.36.Mbfu09&userId=143534224 ),她个人主页的信息必然在异步返回的内容中,不可能会凭空产生。
通过简单观察,我们发现,这个网址后面有一个userId,而Response中也有userId,而且是一样的!
于是,产生一个假设,userId会决定我们进入哪个淘女郎的个人主页。
很幸运,我尝试将userId替换成其他人的userId之后,证实了我的设想,那么这个问题就圆满解决了~
这里,暂时不要考虑网址中的spm,这个东西只是淘宝用来定位的代号
爬虫实现
感觉爬虫分析过程才是最复杂的,都分析好了以后,代码还是很简单的,就不多说了~
本程序会在当前目录根据淘女郎的名字建立文件夹,存放对应图片。
由于每个淘女郎的照片太多了,笔记本硬盘空间不太够了,所以只好指定了页数爬取照片。如果想要爬取多页,只要在外层套一个关于页数的循环就好了~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 import osimport requestsimport reurl_ajax = 'https://mm.taobao.com/tstar/search/tstar_model.do?_input_charset=utf-8' url_base = 'https://mm.taobao.com/self/aiShow.htm?spm=719.7763510.1998643336.71.Yx0DbQ&userId=' params = {} params['q' ] = '' params['viewFlag' ] = 'A' params['searchStyle' ] = '' params['searchRegion' ] = 'city:' params['searchFansNum' ] = '' params['currentPage' ] = 2 params['pageSize' ] = 100 headers = {} headers['User-Agent' ] = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0' resp = requests.get(url_ajax, params=params, headers=headers) uni_str = resp.content.decode(resp.encoding) pattern = re.compile('"city":"(.*?)".*?' + '"height":"(.*?)".*?,' + '"realName":"(.*?)".*?' + '"userId":(.*?),' ) items = re.findall(pattern, uni_str) base_dir = os.getcwd() for item in items: city, height, name, id = item[0 ], item[1 ], item[2 ], item[3 ] if (os.path.exists(name) == False ): os.mkdir(name) path = os.path.join(base_dir, name) url = url_base + id mm_page = requests.get(url) mm_str = mm_page.content.decode(resp.encoding) mm_pattern = re.compile('img.*?src="(.*?)"' ) images = re.findall(mm_pattern, mm_str) num = 1 for image in images: f_url = 'https:' + image.strip() if f_url[-3 :].lower() != 'jpg' and f_url[-4 :].lower() != 'jpeg' : continue print(f_url) try : di = requests.get(f_url) f_path = os.path.join(path, str(num) + '.jpg' ) with open(f_path, 'wb' ) as si: si.write(di.content) num += 1 except : print('Failed:' + f_url)
多进程
运行的时候,我发现速度太慢了,所以就增加了多进程运行~
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 import osimport requestsimport reimport multiprocessingurl_ajax = 'https://mm.taobao.com/tstar/search/tstar_model.do?_input_charset=utf-8' url_base = 'https://mm.taobao.com/self/aiShow.htm?spm=719.7763510.1998643336.71.Yx0DbQ&userId=' params = {} params['q' ] = '' params['viewFlag' ] = 'A' params['searchStyle' ] = '' params['searchRegion' ] = 'city:' params['searchFansNum' ] = '' params['currentPage' ] = 4 params['pageSize' ] = 100 headers = {} headers['User-Agent' ] = 'Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:53.0) Gecko/20100101 Firefox/53.0' resp = requests.get(url_ajax, params=params, headers=headers) uni_str = resp.content.decode(resp.encoding) pattern = re.compile('"city":"(.*?)".*?' + '"height":"(.*?)".*?,' + '"realName":"(.*?)".*?' + '"userId":(.*?),' ) items = re.findall(pattern, uni_str) base_dir = os.getcwd() def download (item) : city, height, name, id = item[0 ], item[1 ], item[2 ], item[3 ] if (os.path.exists(name) == False ): os.mkdir(name) path = os.path.join(base_dir, name) url = url_base + id mm_page = requests.get(url) mm_str = mm_page.content.decode(resp.encoding) mm_pattern = re.compile('img.*?src="(.*?)"' ) images = re.findall(mm_pattern, mm_str) num = 1 for image in images: f_url = 'https:' + image.strip() if f_url[-3 :].lower() != 'jpg' and f_url[-4 :].lower() != 'jpeg' : continue print(f_url) try : di = requests.get(f_url) f_path = os.path.join(path, str(num) + '.jpg' ) with open(f_path, 'wb' ) as si: si.write(di.content) num += 1 except : print('Failed:' + f_url) for item in items: p = multiprocessing.Process(target=download, args=(item, )) p.start()