网页爬虫抓取百度图片(廖雪峰老师的python处理和复杂芜杂的网络框架给整崩溃了)

优采云 发布时间: 2021-09-25 04:10

  网页爬虫抓取百度图片(廖雪峰老师的python处理和复杂芜杂的网络框架给整崩溃了)

  说些什么

  其实一直对python这个语言很感兴趣,但是之前一直在做图像处理相关的事情,所以没怎么关注这种不能触及底层内存处理的语言,但是最近才真正用上通过 C++ 字符。字符串处理和复杂的网络框架崩溃了,看到大家都说python很好玩,所以趁着最近没事的时候学习了python。

  昨天关注了廖雪峰老师的python教程(推荐基础教程)。看了基本的数据结构和逻辑后,我决定直接从一个实际的小项目来实践。最好的语言方式),所以就选择了一个比较简单的python爬虫项目来练习。

  写爬虫最重要的就是了解我们平时访问的网页是什么。其实我们平时访问的网页源代码是一个字符串文件(当然也可以说是二进制文件)

  每次我们在浏览器上输入一个网址,比如这个网址,浏览器会帮我们访问远程服务器,并根据绑定的ip地址发送请求,远程服务器会发送这个网页的源代码直接打包发送给我们的浏览器(html文件格式),然后我们的浏览器会解析这个字符串文件,比如通过div格式化和渲染网页,h1、h2 layouts 显示,继续发送请求给远程服务器为img这些资源获取图片,然后在网页上填写。

  什么是爬虫

  怎么说呢,爬虫,简单来说就是模拟浏览器获取一个网页的源代码。至于你用源代码做什么,没关系。

  说的更复杂一点,爬虫其实就是对所有网页数据处理的综合,比如:自动抓取网页源代码,分析网页数据,获取关键数据并保存,或者自动下载需要的网页图片、音频,和视频。

  那么当我们在写一个pythonm爬虫的时候,我们在写什么呢?

  当我们需要爬虫的时候,一般会遇到比较复杂的数据需求。这个要求对于手工作业来说是非常复杂的。仅此要求就可以由爬虫轻松解决。

  那么首先确定我们的需求,我们需要这个爬虫做什么?

  比如我们认为一个教学网站的数据很有趣,但是它的格式太复杂,或者需要频繁翻页,不能通过复制粘贴轻易获取,爬虫就会起作用。

  总之,我们以一个爬虫的例子来说明。

  爬取百度图片ps:python版-Python 3.7.0

  第一个爬虫当然不能选择太复杂的东西,涉及到很多复杂的网络规则,所以我们来爬一些网站,简单的让爬虫去爬。

  比如抓取下载关键词下的某百度图片的图片数据。

  1、建立需求

  暂时确定以上需求,然后开始写真正的爬虫代码

  2、 观察网页源码

  首先打开百度图片,随意搜索一个关键词。比如这次我会用我最喜欢的*敏*感*词*角色栗山未来来测试

  右键查看网页源码,可以看到每张图片的原创地址都是以一个简单的“objURL”开头,以一个小逗号结尾,如下:

  

  基于此,我们可以确定爬虫应该如何运行。很简单——从网页源码中提取这些url并下载\(^o^)/~

  3、获取网页源码

  其实这一步我是不想写的,只是担心看了我博客刚学python的朋友可能会出错,所以说一下。

  首先,我们需要在python中导入网络库urllib。因为我们需要用到的urlopen和read方法在我的python版本中,直接引用urllib会出错,所以一般使用这个import:import urllib.request

  提取网页源代码的整个方法如下:

  import urllib.request

def get_html(httpUrl):

page = urllib.request.urlopen( httpUrl )#打开网页

htmlCode = page.read( )#读取网页

return htmlCode

  我们可以将这个方法打包成一个py文件,然后直接在其他py文件中导入这个方法,然后直接使用我们写的get_html方法。

  然后将上面得到的二进制文件解码成普通字符串:

  html_code=get_html(search_url)

html_str=html_code.decode(encoding = "utf-8")#将二进制码解码为utf-8编码,即str

  4、提取图片地址

  从网页的源代码中提取关键数据时,实际上是字符串匹配。如果这样估计C++累死我了,当然我也写过类似的,甚至更复杂的,真的是痛苦的回忆。

  这里推荐一个比较简单的字符串搜索和匹配程序-正则表达式,也称为正则表达式。(英文:Regular Expression,在代码中常缩写为regex、regexp或RE)

  当然,如何使用正则表达式我就不多说了。你可以自己搜索每个视频网站,看个大概就够了,或者直接看这里——正则表达式基础

  了解正则表达式的基本逻辑就可以了。

  进入正题,上面的步骤已经分析到每张图片的原创地址开头都有一个很简单的“objURL”,所以我们正则化的关键就是把“objURL”后面的地址取出来。这个很简单,我直接把写好的正则表达式拿出来:

  reg=r'"objURL":"(.*?)",'

  ps:字符串前的r主要是为了防止转义字符丢失导致的字符丢失

  这个规律的作用如下:

  匹配任何以 "objURL":" 开头并以 ", 结尾的字符串

  然后简单地编译这个正则(记得导入 re 包):

  import re

reg=r'"objURL":"(.*?)",'

reg_str = r'"objURL":"(.*?)",' #正则表达式

reg_compile = re.compile(reg_str)

  然后使用上面编译的正则表达式解析第三步得到的字符串,如下:

  pic_list = reg_compile.findall(html_str)

  上面的 pic_list 是一个简单的列表

  输出列表中的数据:

   for pic in pic_list:

print(pic)

  输出如下:

  http://b-ssl.duitang.com/uploads/item/201609/02/20160902174427_4H2V8.jpeg

http://b-ssl.duitang.com/uploads/item/201607/18/20160718133442_cnmKP.jpeg

http://cdnq.duitang.com/uploads/item/201504/05/20150405H2814_VvZfS.jpeg

http://wxpic.7399.com/nqvaoZtoY6GlxJuvYKfWmZlkxaJhpc-bna-SmqKfYm/lmqN-oo5Gop3nXfWqYhdpxmoPGZHOozqx7fpyToXCcmYaMvIe0g6GuocOqdnmP1WGrsLCZoY-ub36elaeBr42tb6nSh5qApHqCrnyPq6K0emd6152Ti7Crh3ZiYHGvq5acpNpu

http://i1.hdslb.com/bfs/archive/801e00579f4b5bd2b83dcdd665dcc7819fce4470.jpg

http://wxpic.7399.com/nqvaoZtoY6GlxJuvYKfWmZlkxaJhpc-bna-SmqKfYm/lmqN-oo5Gop3nXfWqYhdpxmoPGZHOozqx7fpyToXCcmYaHv3vFrntnotGGeaRpsKp8nbqmZnCXh5-tqZOIrqOgmZDWmsNxoJ2bs4Jsqoy-fm2BznWlf82clpxiYHGvq5acpNpu

  可以清楚的看到,有些地址不是图片地址。这可以说是我正则化的问题,但也无伤大雅(其实我也懒得改了)。一点判断就可以完美解决(由于所有图片地址都以g结尾,比如png、jpg、jpeg^_^)

  for pic in pic_list:

if pic[len(pic)-1]=='g':

print(pic)

  完美解,w(゚Д゚)w

  ps:哈哈哈,这里当然是玩笑了,大家记得想好办法改正,算是小测试,毕竟真的是无害的。

  5、下载图片

  下载图片也很简单。正如我开头所说的,图片实际上是存在于远程服务器上的图片文件。只要服务器允许,我们可以很容易的通过GET请求得到这张图片。毕竟,浏览器也会这样做。,至于你得到的,没人管它是用来实际填网页还是给自己用。

  python中下载图片的方式有很多种,如下三种

  (以下代码不是我写的,不知道版本对不对,如有错误请自行百度。第一种在我的版本中没有问题):

  def urllib_download(url):

from urllib.request import urlretrieve

urlretrieve(url, '1.png')

def request_download(url):

import requests

r = requests.get(url)

with open('1.png', 'wb') as f:

f.write(r.content)

def chunk_download(url):

import requests

r = requests.get(url, stream=True)

with open('1.png', 'wb') as f:

for chunk in r.iter_content(chunk_size=32):

f.write(chunk)

  所以我们只需要下载上面列表中的每个图片网址。我选择了上面的第一个。这是urllib.request中存在的一个方法,定义如下:

  urllib.request.urlretrieve(url, filename, reporthook, data)

参数说明:

url:外部或者本地url

filename:指定了保存到本地的路径(如果未指定该参数,urllib会生成一个临时文件来保存数据);

reporthook:是一个回调函数,当连接上服务器、以及相应的数据块传输完毕的时候会触发该回调。我们可以利用这个回调函数来显示当前的下载进度。

data:指post到服务器的数据。该方法返回一个包含两个元素的元组(filename, headers),filename表示保存到本地的路径,header表示服务器的响应头。

  然后一个简单的循环下载就可以了:

  def download_pic(pic_adr,x):

urllib.request.urlretrieve(pic_adr, '%s.jpg' %x)

# './images/%s.jpg',这里也可以自己选择创建一个文件吧所有图片放进去,而不是直接放在当前目录下

x=0

for pic in pic_list:

if pic[len(pic)-1]=='g':

print(pic)

download_pic(pic,x)

x += 1

  当然需要为每张图片选择一个本地名称,只需将名称增加1234即可。

  这样,我们就结束了整个爬取过程。执行后效果如下:

  

  可以看到,效果还是不错的。毕竟,只要把它放在那里,让它自己下载。还可以考虑如何翻页的效果。事实上,这很简单。我就讲实现一个变化。关键词的效果提醒大家(其实是因为我有点懒,不想写了)

  6、更改搜索关键词

  看百度搜索页面的网址:

  

  观察这个网址,我们很容易发现原来最后一个关键字是关键词。复制就改了,但是复制之后就不简单了:

  http://image.baidu.com/search/flip?tn=baiduimage&ipn=r&ct=201326592&cl=2&lm=-1&st=-1&fm=result&fr=&sf=1&fmq=1546589116401_R&pv=&ic=0&nc=1&z=&hd=&latest=&copyright=&se=1&showtab=0&fb=0&width=0&height=0&face=0&istype=2&ie=utf-8&ctd=1546589116402%5E00_1519X723&word=%E6%A0%97%E5%B1%B1%E6%9C%AA%E6%9D%A5

  为什么word变成%E6%A0%97%E5%B1%B1%E6%9C%AA%E6%9D%A5

  这么一堆东西?

  很简单,因为url是ASCII码,而这里我们用的是中文,只要稍微操作一下就可以转:

  keyword=urllib.parse.quote(keyword)

search_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=1546580974349_R&pv=&ic=0&nc=1&z=&hd=&latest=&copyright=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&ctd=1546580974351%5E00_1519X723&word="

search_url=search_url+keyword #加上关键字

  urllib.parse.quote 是解码后的代码,在最后加上关键字就OK了。

  简单,这个简单的python爬虫就完成了。.

  虽然还是想自己写字符串识别,但是regular真的好用。建议多学习一些常规的骚技能。

  就这样。

  如需修改,请自行复制完整代码并进行更改。下载多个页面也是很简单的操作,就不多说了,还是可以加多线程,代理,动态ip。无论如何,这就是我的第一个爬虫。

  完整源码(百度图片爬虫)

  import urllib

import time

from urllib.request import urlretrieve

import re

import urllib.request

def get_html(httpUrl):#获取网页源码

page = urllib.request.urlopen( httpUrl )#打开网页

htmlCode = page.read( )#读取网页

return htmlCode

def get_keyword_urllist(keyword):#爬取当前关键词下的图片地址

keyword=urllib.parse.quote(keyword)

search_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=1546580974349_R&pv=&ic=0&nc=1&z=&hd=&latest=&copyright=&se=1&showtab=0&fb=0&width=&height=&face=0&istype=2&ie=utf-8&ctd=1546580974351%5E00_1519X723&word="

search_url=search_url+keyword #加上关键字

html_code=get_html(search_url)

html_str=html_code.decode(encoding = "utf-8")#将二进制码解码为utf-8编码,即str

reg_str = r'"objURL":"(.*?)",' #正则表达式

reg_compile = re.compile(reg_str)

pic_list = reg_compile.findall(html_str)

return pic_list

keyword="栗山未来"#自己修改,或者自己写个input或者一个txt自己读就完事了,甚至你写一个配置表,把爬取数量、爬取关键词、爬取图片大小都写好都可以

pic_list=get_keyword_urllist(keyword)

x=0

for pic in pic_list:

if pic[len(pic)-1]=='g':

print(pic)

name = keyword+str(x)

time.sleep(0.01)

urllib.request.urlretrieve(pic, './images/%s.jpg' %name)

x += 1

  如果不行,请检查收录的模板是否正确或版本是否正确。

  重点

  最后运行上面的源码,应该会发现虽然可以下载,但是下载速度太慢了。解决它需要几秒钟,但如果它更慢,则可能需要十秒钟以上。

  针对这种情况,我重写了上面的代码,加入了多线程处理,将爬取时间缩短到1s以内。我是直接上传到我的github上的,大家可以自己下载。

  快速爬取百度图片-爬虫1.0版

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线