拍是一种源于欧美国家的文化,最早是源于时尚杂志的需求,用相机捕捉街上的时尚元素,还要传递来自民间的流行信息,于是所谓“街头秀”就应运而生。
一般来说,一次专业的街拍,必须捕捉到被拍者衣服的细节.搭配和牌子。如今“街拍”活动正逐步成为国内年轻人一项新的街头文化活动。
临近夏天,人们逐渐穿的凉快起来,街上也越来越多的美女,帅哥。如果你去今日头条搜索街拍,你会看到非常有养眼的图片。今天就教大家如何爬取今日头条街拍的图片。
在 Chrome 浏览器上,我们先进入今日头条的官网,在搜索栏上输入街拍,就会显示很多街拍的图片。我们按 F12 在开发者工具中进行具体的分析。
今日头条的数据是用 json 来请求的,所以我们在 Network 的 Headers 中可以看到它的请求参数,这部分就是我们需要的请求体中的参数。我们就可以利用 urlencode() 来构造这请求参数。
在代码中我把 offset, keyword 作为函数的参数,这样我们就可以控制抓取的数量和要抓取的内容。
对应的代码:
def get_page(offset, keyword):
data={
?'offset': offset,
?'format': 'json',
?'keyword': keyword,
?'autoload': 'true',
?'count': '20',
?'cur_tab': '1'
}
params=urlencode(data)
url='https://www.toutiao.com/search_content/' + '?' + params
try:
?response=requests.get(url)
?if response.status_code==200:
return response.json()
except requests.ConnectionError:
?return None
我们这次的程序主要是抓取图片,所以我们在请求的网页中寻找下是否有我们所要的图片数据。
点开 Preview 我们就可以看到有个 data 关键字
这里面就有我们需要的图片 url 的数据。其中图片的 url 就保存在 image_list 中。
在这里还有我们需要的 title 信息。
对应的代码:
def get_images(json):
data=json.get('data')
if data:
?for item in data:
image_list=item.get('image_list')
title=item.get('title')
for image in image_list:
yield {
?'image': image.get('url'),
?'title': title
}
目标 url 和内容我们已初步的分析完,接下来就是把图片下载下来保存到本地文件夹。
对应的代码:
def save_image(item):
? if not os.path.exists('{0}/{1}'.format('image', item.get('title'))):
os.mkdir('{0}/{1}'.format('image', item.get('title')))
? try:
local_image_url=item.get('image')
new_image_url=local_image_url.replace('list', 'large')
response=requests.get('http:' + new_image_url)
if response.status_code==200:
file_path='{0}/{1}/{2}.{3}'.format('image', item.get('title'), hashlib.md5(response.content).hexdigest(), 'jpg')
if not os.path.exists(file_path):
? with open(file_path, 'wb') as f:
f.write(response.content)
else:
? print('Already Downloaded', file_path)
? except requests.ConnectionError:
print('Failed to save image')
最后在 main 中开启线程,来提高效率。整个程序运行后,会把图片自动以标题分类保存到当前工程目录。
对应代码:
def main(offset):
json=get_page(offset, '街拍')
for item in get_images(json):
?print(item)
?save_image(item)
if __name__=='__main__':
pool=Pool()
groups=([x * 20 for x in range(GROUP_START, GROUP_END + 1)])
pool.map(main, groups)
pool.close()
pool.join()
完整代码我已上传到 Github 上,需要的同学可以自己去下载。