从谷歌搜索下载前1000个图像

时间:2012-07-17 14:04:48

标签: regex image shell uri

我搜索谷歌图片

http://www.google.com/search?hl=en&q=panda&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.,cf.osb&biw=1287&bih=672&um=1&ie=UTF-8&tbm=isch&source=og&sa=N&tab=wi&ei=qW4FUJigJ4jWtAbToInABg

结果是成千上万的照片。我正在寻找一个将下载第一个n图像的shell脚本,例如1000或500。

我该怎么做?

我想我需要一些高级正则表达式或类似的东西。我尝试了很多东西,但无济于事,有人可以帮我吗?

11 个答案:

答案 0 :(得分:19)

更新3:我修改了脚本以使用phantomjs 2.x.

更新2:我修改了脚本以使用phantomjs。安装起来比较困难,但至少可以再次使用。 http://sam.nipl.net/b/google-images http://sam.nipl.net/b/google-images.js

更新1:不幸的是,这不再适用。现在需要Javascript和其他魔法才能找到图像所在的位置。以下是雅虎图片搜索脚本的一个版本:http://sam.nipl.net/code/nipl-tools/bin/yimg

原始回答:我为此共同攻击了一些内容。我通常会编写较小的工具并一起使用它们,但是你要求一个shell脚本,而不是三十个。这是故意密集的代码。

http://sam.nipl.net/code/nipl-tools/bin/google-images

到目前为止似乎运作良好。如果您可以改进它,或者建议任何更好的编码技术(假设它是一个shell脚本),请告诉我。

#!/bin/bash
[ $# = 0 ] && { prog=`basename "$0"`;
echo >&2 "usage: $prog query count parallel safe opts timeout tries agent1 agent2
e.g. : $prog ostrich
       $prog nipl 100 20 on isz:l,itp:clipart 5 10"; exit 2; }
query=$1 count=${2:-20} parallel=${3:-10} safe=$4 opts=$5 timeout=${6:-10} tries=${7:-2}
agent1=${8:-Mozilla/5.0} agent2=${9:-Googlebot-Image/1.0}
query_esc=`perl -e 'use URI::Escape; print uri_escape($ARGV[0]);' "$query"`
dir=`echo "$query_esc" | sed 's/%20/-/g'`; mkdir "$dir" || exit 2; cd "$dir"
url="http://www.google.com/search?tbm=isch&safe=$safe&tbs=$opts&q=$query_esc" procs=0
echo >.URL "$url" ; for A; do echo >>.args "$A"; done
htmlsplit() { tr '\n\r \t' ' ' | sed 's/</\n</g; s/>/>\n/g; s/\n *\n/\n/g; s/^ *\n//; s/ $//;'; }
for start in `seq 0 20 $[$count-1]`; do
wget -U"$agent1" -T"$timeout" --tries="$tries" -O- "$url&start=$start" | htmlsplit
done | perl -ne 'use HTML::Entities; /^<a .*?href="(.*?)"/ and print decode_entities($1), "\n";' | grep '/imgres?' |
perl -ne 'use URI::Escape; ($img, $ref) = map { uri_unescape($_) } /imgurl=(.*?)&imgrefurl=(.*?)&/;
$ext = $img; for ($ext) { s,.*[/.],,; s/[^a-z0-9].*//i; $_ ||= "img"; }
$save = sprintf("%04d.$ext", ++$i); print join("\t", $save, $img, $ref), "\n";' |
tee -a .images.tsv |
while IFS=$'\t' read -r save img ref; do
wget -U"$agent2" -T"$timeout" --tries="$tries" --referer="$ref" -O "$save" "$img" || rm "$save" &
procs=$[$procs + 1]; [ $procs = $parallel ] && { wait; procs=0; }
done ; wait

特点:

  • 1500字节以下
  • 解释了使用情况,如果没有args运行
  • 并行下载完整图片
  • 安全搜索选项
  • 图片大小,类型等opts string
  • 超时/重试选项
  • 冒充googlebot获取所有图片
  • 数字图片文件
  • 保存元数据

我会在一段时间内发布一个模块化版本,以表明它可以通过一组shell脚本和简单的工具很好地完成。

答案 1 :(得分:6)

我认为你不能单独使用正则表达式完成整个任务。这个问题有3个部分 -

1 。提取所有图片的链接-----&gt;不能用正则表达式完成。您需要使用基于Web的语言。谷歌有API以编程方式执行此操作。查看herehere

2 。假设您使用某些基于Web的语言成功完成了第一步,您可以使用以下正则表达式使用前瞻提取精确的图像网址

(?<=imgurl=).*?(?=&)

以上正则表示 - 抓取所有内容从imgurl=开始,直到遇到&符号See here例如,我获取了搜索结果的第一张图片的网址并提取了图片网址。

我是如何到达上述正则表达式的?通过检查图像搜索中找到的图像的链接。

3 。现在您已获得图片网址,请使用一些基于网络的语言/工具下载您的图片。

答案 2 :(得分:2)

与使用regexp在shell中执行此操作相比,如果您使用可以实际解析HTML本身的内容(例如PHP's DOMDocument class),则可能会更容易。

如果您只使用shell并且需要啜饮图片网址,那么您可能不会完全失去运气。 Regular Expressions are inappropriate for parsing HTML,因为HTML不是regular language。但是,如果您的输入数据具有高度可预测性,您仍然可以顺利通过。 (无法保证这一点,因为Google会定期更新其产品和服务,而且无需事先通知。)

也就是说,在您在问题中提供的网址的输出中,每个图片网址似乎都嵌入到链接到/imgres?…的锚点中。如果我们可以解析这些链接,我们可以收集他们需要的东西。在这些链接中,图片网址似乎以&amp;imgurl=开头。所以让我们抓住这个。

#!/usr/local/bin/bash

# Possibly violate Google's terms of service by lying about our user agent
agent="Mozilla/5.0 (X11; FreeBSD amd64; rv:12.0) Gecko/20100101 Firefox/12.0"

# Search URL
url="http://www.google.com/search?hl=en&q=panda&bav=on.2,or.r_gc.r_pw.r_cp.r_qf.,cf.osb&biw=1287&bih=672&um=1&ie=UTF-8&tbm=isch&source=og&sa=N&tab=wi&ei=qW4FUJigJ4jWtAbToInABg"

curl -A "$agent" -s -D- "$url" \
 | awk '{gsub(/<a href=/,"\n")} 1' \
 | awk '
   /imgres/ {
     sub(/" class=rg_l >.*/, "");       # clean things up
     split($0, fields, "\&amp;");       # gather the "GET" fields
     for (n=1; n<=length(fields); n++) {
       split(fields[n], a, "=");        # split name=value pair
       getvars[a[1]]=a[2];              # store in array
     }
     print getvars["imgurl"];           # print the result
   }
 '

我正在使用两个awk命令,因为......好吧,我很懒,这是生成行的最快捷方式,我可以很容易地找到“imgres”字符串。人们可以花更多的时间来清理它并使它变得更优雅,但是收益递减的规律决定了这一点,就这一点而言。 : - )

此脚本返回一个URL列表,您可以使用其他shell工具轻松下载这些URL。例如,如果脚本名为getimages,则:

./getimages | xargs -n 1 wget

请注意,当我使用您在问题中指定的搜索网址运行时,Google似乎只向我发送了83个结果(而非1000个)。这可能只是谷歌在我接近底部“扩展”页面(使用JavaScript)之前通常会向浏览器发送的第一页。 正确处理此问题的方法是根据Pavan的回答使用Google的搜索API,如果您每天进行超过100次搜索,则使用谷歌搜索他们的数据。

答案 3 :(得分:1)

工作量太大了?为什么不使用Bulk Image Downloader? 它有100个图像限制。

需要为拥有Java图像查看器的网站编码。

答案 4 :(得分:0)

不要试图解析HTML(非常难以破解),而应考虑@Paven在其答案中突出显示的API。

此外,请考虑使用已尝试执行类似操作的工具。 WGET(web-get)具有类似蜘蛛的功能,用于跟踪链接(特别是指定的文件类型)。请参阅StackOverflow问题'how do i use wget to download all images into a single folder'的答案。

正则表达式非常有用,但我不认为它是在这种背景下 - 记住正则表达式的口头禅:

  

有些人在面对问题时会想“我知道,我会使用正则表达式”。现在他们有两个问题。

     

- Jamie Zawinski

答案 5 :(得分:0)

有Pavan Manjunath的回应,如果你想要身高和高度图像宽度

(?<=imgurl=)(?<imgurl>.*?)(?=&).*?(?<=h=)(?<height>.*?)(?=&).*?(?<=w=)(?<width>.*?)(?=&)

您获得3个正则表达式组 imgurl height &amp;带有信息的 width

答案 6 :(得分:0)

我找到了一种更简单的方法this tool我可以确认它在本文中的效果很好。 screenshot

向开发者提出的功能请求:

  • 预览图片以验证图片是否正确。
  • 允许顺序输入多个术语(即批处理)。

答案 7 :(得分:0)

Python脚本:从Google图片搜索下载全分辨率图片 目前每个查询下载100张图片

from bs4 import BeautifulSoup
import requests
import re
import urllib2
import os
import cookielib
import json

def get_soup(url,header):
    return BeautifulSoup(urllib2.urlopen(urllib2.Request(url,headers=header)),"html.parser")


query = raw_input("query image")# you can change the query for the image  here
image_type="ActiOn"
query= query.split()
query='+'.join(query)
url="https://www.google.co.in/search?q="+query+"&source=lnms&tbm=isch"
print url
#add the directory for your image here
DIR="C:\\Users\\Rishabh\\Pictures\\"+query.split('+')[0]+"\\"
header={'User-Agent':"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/43.0.2357.134 Safari/537.36"
}
soup = get_soup(url,header)


ActualImages=[]# contains the link for Large original images, type of  image
for a in soup.find_all("div",{"class":"rg_meta"}):
    link , Type =json.loads(a.text)["ou"]  ,json.loads(a.text)["ity"]
    ActualImages.append((link,Type))

print  "there are total" , len(ActualImages),"images"


###print images
for i , (img , Type) in enumerate( ActualImages):
    try:
        req = urllib2.Request(img, headers={'User-Agent' : header})
        raw_img = urllib2.urlopen(req).read()
        if not os.path.exists(DIR):
            os.mkdir(DIR)
        cntr = len([i for i in os.listdir(DIR) if image_type in i]) + 1
        print cntr
        if len(Type)==0:
            f = open(DIR + image_type + "_"+ str(cntr)+".jpg", 'wb')
        else :
            f = open(DIR + image_type + "_"+ str(cntr)+"."+Type, 'wb')


        f.write(raw_img)
        f.close()
    except Exception as e:
        print "could not load : "+img
        print e

我在这里发布我的解决方案我在以下问题上发布的原始解决方案 https://stackoverflow.com/a/28487500/2875380

答案 8 :(得分:0)

如何使用此库?google-images-download

对于仍在寻找下载100个图像的好方法的人,可以使用此命令行参数代码。

答案 9 :(得分:0)

我用它下载了1000张图片,并且100%为我工作:atif93/google_image_downloader

下载后,打开终端并安装Selenium

$ pip install selenium --user

然后检查您的python版本

$ python --version

如果运行python 2.7,则要下载1000张比萨运行图像:

$ python image_download_python2.py 'pizza' '1000'

如果运行python 3,则要下载1000张比萨运行图像:

$ python image_download_python3.py 'pizza' '1000'

明细为:

python image_download_python2.py <query> <number of images>
python image_download_python3.py <query> <number of images>

query 是您要查找的图像名称,图像数是1000。在上面的示例中,我的查询是披萨,我希望获得1000张图像

答案 10 :(得分:-1)

github上有其他库 - 这看起来非常好 https://github.com/Achillefs/google-cse

g = GoogleCSE.image_search('Ian Kilminster')
img = g.fetch.results.first.link
file = img.split('/').last
File.open(file,'w') {|f| f.write(open(img).read)} 
`open -a Preview #{file}`