python爬虫,爬取百度图片

这两天尝试在爬取百度图片时,遇到了不少坑,有几处问题还不太明白,先记录下来,待日后解决。

问题如下:

1. 百度图片的网页有两种:

http://image.baidu.com/search/index?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&oe=utf-8&word=people&fp=result&

http://image.baidu.com/search/flip?tn=baiduimage&ps=1&ct=201326592&lm=-1&cl=2&nc=1&ie=utf-8&oe=utf-8&word=people&fp=result&

两者只有加下划线的部分不同,但是关键字为index的url图片是动态加载的,使用xpath无法解析到图片的链接地址

关键字为flip的是固定页面,每页显示固定张数的图片,但是从浏览器端看到只有30张,但是通过requests.get获取到的图片url却有60个,不是很理解这一点。

我写的爬虫使用的是解析关键字为flip的url

2. 在获取到html.text后,通过正则表达式来筛选出图片的源地址

re.findall('"objURL":"(.*?)",', html, re.S)

这一句是借鉴了其他人的写法,对于(.*?)的理解还有待加深

3. 在下载图片的时候,有些链接居然没有注明图片的格式,会导致图片下载失败,这一点我在代码里做了简单规避,自动补上.jpg

4. 在解析html的时候,没有搜索到跟图片总数相关的关键字

下面附上代码

#此爬虫可以用来爬取百度图片,并下载到本地
#支持关键字输入和指定张数

from lxml import etree
import requests
import re
import urllib
import json
import time
import os

local_path = 'E:\python\pic\\'
keyword = input('请输入想要搜索图片的关键字:')
first_url = 'http://image.baidu.com/search/flip?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1530850407660_R&pv=&ic=0&nc=1&z=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&ctd=1530850407660%5E00_1651X792&word={}'.format(keyword)
want_download = input('请输入想要下载图片的张数:')

global page_num
page_num = 1
global download_num
download_num = 0

#这个函数用来获取图片格式
def get_format(pic_url):
	#url的末尾存着图片的格式,用split提取
	#有些url末尾并不是常见图片格式,此时用jpg补全
	t = pic_url.split('.')
	if t[-1].lower() != 'bmp' and t[-1].lower() != 'gif' and t[-1].lower() != 'jpg' and t[-1].lower() != 'png':
		pic_format = 'jpg'
	else:
		pic_format = t[-1]
	return pic_format

#这个函数用来获取下一页的url
def get_next_page(page_url):
	global page_num
	html = requests.get(page_url).text
	with open('html_info.txt', 'w', encoding='utf-8') as h:
		h.write(html)
	selector = etree.HTML(html)
	try:
		msg = selector.xpath('//a[@class="n"]/@href')
		print(msg[0])
		next_page = 'http://image.baidu.com/' + msg[0]
		print('现在是第%d页' % (page_num + 1))
	except Exception as e:
		print('已经没有下一页了')
		print(e)
		next_page = None
	page_num = page_num + 1
	return next_page

#这个函数用来下载并保存图片
def download_img(pic_urls):
	count = 1
	global download_num
	for i in pic_urls:
		time.sleep(1)
		try:
			pic_format = get_format(i)
			pic = requests.get(i, timeout=15)
			#按照格式和名称保存图片
			with open(local_path + 'page%d_%d.%s' % (page_num, count, pic_format), 'wb') as f:
				f.write(pic.content)
				print('成功下载第%s张图片: %s' % (str(count), str(pic.url)))
				count = count + 1
				download_num = download_num + 1
		except Exception as e:
			print('下载第%s张图片时失败: %s' % (str(count), str(pic.url)))
			print(e)
			count = count + 1
			continue
		finally:
			if int(want_download) == download_num:
				return 0

#这个函数用来提取url中图片的url
def get_pic_urls(web_url):
	html = requests.get(web_url).text
	#通过正则表达式寻找图片的地址,
	pic_urls = re.findall('"objURL":"(.*?)",', html, re.S)
	#返回图片地址,是一个list
	return pic_urls

if __name__ == "__main__":
	while True:
		pic_urls = get_pic_urls(first_url)
		t = download_img(pic_urls)
		if t==0:
			break
		next_url = get_next_page(first_url)
		if next_url == None:
			print('已经没有更多图片')
			break
		pic_urls = get_pic_urls(next_url)
		t = download_img(pic_urls)
		if t==0:
			break
		first_url = next_url
	print('已经成功下载%d张图片' %download_num)


猜你喜欢

转载自blog.csdn.net/lsy_07/article/details/80950189