网页爬虫抓取百度图片(像是这样%AB%98%(图)(组图))
优采云 发布时间: 2022-01-12 09:04网页爬虫抓取百度图片(像是这样%AB%98%(图)(组图))
我最近在玩机器学习,想创建一个识别*敏*感*词*图片的训练集。我因没有太多*敏*感*词*图片而苦恼。后来突然想到可以用百度图片,于是写了一个简单的爬虫来抓取百度图片(图片关于一个关键词)
第一步是找到搜索图片的url。
打开百度图片网页,搜索“高清*敏*感*词*”,检查元素,检查网络,清除网络请求数据,将页面滚动到底部,看到自动加载更多,然后找到加载更多数据的url在网络请求中。像这样 %E9%AB%98%E6%B8%85%E5%8A%A8%E6%BC%AB&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&word= % E4%BA%8C%E6%AC%A1%E5%85%83&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&pn=60&rn=30&gsm=1000000001e&81=
对比几个加载较多的URL,发现rn参数是每页显示的次数,pn参数是已经请求的次数。通过修改rn参数和pn参数,观察返回的数据,发现每页最多只能有60个,即最大rn设置为60.
第二步是分析返回的数据。
通过浏览器请求上面的url,在页面上看到一个超级json。分析后发现图片的url是thumbURL、middleURL、hoverurl这三个属性,在返回的字符串中搜索这三个属性的编号,发现该编号与分页数一模一样. 通过浏览器打开这三个url,发现thumburl比middleUrl大,和hoverUrl是同一个url。其实还有一个objUrl(原图)可以用,但是url不稳定,有时候404,有时候访问被拒绝。
然后代码
我的 python 版本是 2.7
更新于 2017 年 2 月 11 日
1.保存的图片改成原来的高清大图OjbUrl
2.修改使用方法,可以在命令行输入搜索关键字
3.随时保存,保存前不再需要搜索所有图片。
百度图片搜索.py
#coding=utf-8
from urllib import quote
import urllib2 as urllib
import re
import os
class BaiduImage():
def __init__(self, keyword, count=2000, save_path="img", rn=60):
self.keyword = keyword
self.count = count
self.save_path = save_path
self.rn = rn
self.__imageList = []
self.__totleCount = 0
self.__encodeKeyword = quote(self.keyword)
self.__acJsonCount = self.__get_ac_json_count()
self.user_agent = "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36"
self.headers = {'User-Agent': self.user_agent, "Upgrade-Insecure-Requests": 1,
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8",
"Accept-Encoding": "gzip, deflate, sdch",
"Accept-Language": "zh-CN,zh;q=0.8,en;q=0.6",
"Cache-Control": "no-cache"}
# "Host": Host,
def search(self):
for i in range(0, self.__acJsonCount):
url = self.__get_search_url(i * self.rn)
response = self.__get_response(url).replace("\\", "")
image_url_list = self.__pick_image_urls(response)
self.__save(image_url_list)
def __save(self, image_url_list, save_path=None):
if save_path:
self.save_path = save_path
print "已经存储 " + str(self.__totleCount) + "张"
print "正在存储 " + str(len(image_url_list)) + "张,存储路径:" + self.save_path
if not os.path.exists(self.save_path):
os.makedirs(self.save_path)
for image in image_url_list:
host = self.get_url_host(image)
self.headers["Host"] = host
with open(self.save_path + "/%s.jpg" % self.__totleCount, "wb") as p:
try:
req = urllib.Request(image, headers=self.headers)
# 设置一个urlopen的超时,如果10秒访问不到,就跳到下一个地址,防止程序卡在一个地方。
img = urllib.urlopen(req, timeout=20)
p.write(img.read())
p.close()
self.__totleCount += 1
except Exception as e:
print "Exception" + str(e)
p.close()
if os.path.exists("img/%s.jpg" % self.__totleCount):
os.remove("img/%s.jpg" % self.__totleCount)
print "已存储 " + str(self.__totleCount) + " 张图片"
def __pick_image_urls(self, response):
reg = r'"ObjURL":"(http://img[0-9]\.imgtn.*?)"'
imgre = re.compile(reg)
imglist = re.findall(imgre, response)
return imglist
def __get_response(self, url):
page = urllib.urlopen(url)
return page.read()
def __get_search_url(self, pn):
return "http://image.baidu.com/search/acjson?tn=resultjson_com&ipn=rj&ct=201326592&is=&fp=result&queryWord=" + self.__encodeKeyword + "&cl=2&lm=-1&ie=utf-8&oe=utf-8&adpicid=&st=-1&z=&ic=0&word=" + self.__encodeKeyword + "&s=&se=&tab=&width=&height=&face=0&istype=2&qc=&nc=1&fr=&pn=" + str(pn) + "&rn=" + str(self.rn) + "&gsm=1000000001e&1486375820481="
def get_url_host(self, url):
reg = r'http://(.*?)/'
hostre = re.compile(reg)
host = re.findall(hostre, url)
if len(host) > 0:
return host[0]
return ""
def __get_ac_json_count(self):
a = self.count % self.rn
c = self.count / self.rn
if a:
c += 1
return c
使用示例
运行.py
#coding=utf-8
from BaiduImageSearch import BaiduImage
import sys
keyword = " ".join(sys.argv[1:])
save_path = "_".join(sys.argv[1:])
if not keyword:
print "亲,你忘记带搜索内容了哦~ 搜索内容关键字可多个,使用空格分开"
print "例如:python run.py 男生 头像"
else:
search = BaiduImage(keyword, save_path=save_path)
search.search()
ps:记得把_init_.py文件添加到两个文件的同一目录下!!!
run 方法,python run.py 关键字 1 关键字 2 关键字 3…
一般搜索超过1900条就没有了。