学习爬虫有一段日子,一直都是看博客学习总是一知半解。面试了一次爬虫工程师,才感觉自己的学习方法出了问题,找到一本书来系统学习,才有点通。
开始京东手机类图片的爬虫。。。。。。。。。。。。。
这里我们用到了re库(正则表达式)和urllib.request库,首先打开京东-->找到手机类,对应的网址即为我们要爬取的第一个网页,对应界面如图1所示:
r如果想爬取不止这一个页面的图片,则可以找到下一页,单击之后看一下网址发生了什么变化,https://list.jd.com/list.htmlcat=9987,653,655&page=2&sort=sort_rank_asc&trans=1&JL=6_0_0&ms=6#J_main,由此可以推知page字段是我们爬取网页时需要的,所以我们可以发现获取第几页是通过URL网址识别的。这个可以验证,当我们把page=6时,即网址换为https://list.jd.com/list.html?cat=9987,653,655&page=6,此时展示的是第六页的手机商品列表。此外,我们想自动获取多个网页可以使用for循环实现,每次循环后对应网址中的page字段值加一,自动切换到下一页。
观察网页,我们会发现爬取的图片中存在干扰图片,如图2所示:
所以,我们先用一次正则表达式把无关图片去掉。单击F12,找到源代码。那么如何找到我们需要的图片呢?如下图3所示的小技巧,先单击1,然后在网页中知道我们需要爬取的第一个图片并指向它,这时你会发现对应的代码部分会自动变色。
可以多翻几页或者多找几个图片观察会发现图4,<div id="plist">这个代码距离我们需要爬取的图片距离最近并且在页面中是唯一的,说明我们可以把它作为有效信息的起始过滤位置。
那么结尾的位置,我们去哪找呢?可以按照图3的方法指到网页末尾的翻页处查看对应源代码中距离相对较近并在页面中唯一的一小段代码的位置如图5所示,可以把“<div class="page clearfix">”作为结束的标识。则我们的第一个正则表达式可以构造为:pat1='<div id="plist".*<div class="page clearfix">'
OK!在第一次过滤的基础上再将图片链接信息过滤出来。此时我们可以观察一下图片链接的不同之处。比如以下两张图片的对应源代码:
会发现这两张图的基本格式是一样的,据此可以根据该规律构造出提取图片的正则表达式:
pat2='<img width="220" data-img="1" data-lazy-img="//(.+?.jpg)">'
具体的编程思路如下:
1,自定义一个爬取图片的函数,负责爬取一个网页中需要的图片。
爬取过程为:使用build_opener()修改报头的方法模拟浏览器访问网页。定义一个变量存储对应的User-Agent信息,定义的格式为("User-Agent",具体信息,)具体信息为:"Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36"一般网页的user-agent是一样的,故可以建立一个txt保存下来不用每次都查找一次。然后需要使用urllib.request.build_opener()创建自定义的opener对象并赋给变量opener,接下来设置opener对象的addheaders,即设置对应的头信息,设置格式为:"对象名.addheaders=[头信息]",设置好信息后,我们可以使用opener对象的open()方法打开对应的网址了。此时,打开操作是已经具有头信息的打开操作行为,即模仿为浏览器去打开,格式是"opener对象名.open(url地址)"。打开对应网址后,再使用read()方法读取对应数据,并赋给data变量。到此为止你已经学会爬取整个网页了,(当然记得把网页的格式转化为字符串格式)
然后根据第一个正则表达式进行第一次信息过滤,在第一次过滤结果的基础上进行第二次正则表达式的过滤,提取出的图片链接存储在一个列表中,随后遍历该列表并通过urllib.request.urlretrieve(imageurl,filename=imagename)存储到本地(PS:imagename设为本地文件地址),
最后,为了避免程序中途崩溃,可以建立异常处理,这样即使某个图片不能爬取也会执行x+=1自动跳到下一个图片
2,通过for循环将该分类下的所有网页都爬取一遍,链接构造为:url="http://list.jd.com/list.html?cat=9987,653,655&page="+str(i),在for循环里面,每一次循环对应的i自动加1,每次循环通过调用1中函数实现该页图片的爬取
完整代码如下:(亲测有效)
#...........@author :潘雪雯
#...........@time :2018.04.15.21:19
#...........@software:window7+pycharm+python3.6
#...........@abstract:爬取京东手机类图片
import re
import urllib.request
#简历一个爬取图片的自定义函数,该函数负责爬取一个页面下的我们最想爬取的图片
def craw(url,page):
# req = urllib.request.Request(url)
headers=("User-Agent","Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.87 Safari/537.36")
#获取对应网页的全部源代码
opener = urllib.request.build_opener()
opener.addheaders=[headers]
html1 = opener.open(url).read()
html1 =str(html1)
#进行第一次信息过滤
pat1='<div id="plist".*<div class="page clearfix">'
#findall()函数得到的是一个列表
result1 =re.compile(pat1,re.S).findall(html1)
print(result1)
result2=result1[0]
#第二次过滤提取该网页所以目标图片的链接并存储在一个列表中
pat2='<img width="220" height="220" data-img="1" data-lazy-img="//(.+?\.jpg)">'
imagelist= re.compile(pat2).findall(result2)
x=1
for imageurlin imagelist:
imagename =r"E:/Program Files/编程/data/picture"+str(page)+str(x)+".jpg"
imageurl ="http://"+imageurl
print(imageurl)
try:#该函数可以直接将对应信息写入本地文件
urllib.request.urlretrieve(imageurl,r"E:/Program Files/编程/data/picture"+str(page)+str(x)+".jpg")
except urllib.error.URLErroras e:
if hasattr(e,"code"):
x+=1
if hasattr(e,"reason"):
x+=1
x+=1
for iin range(1,167):
url ="https://list.jd.com/list.html?cat=9987,653,655&page="+str(i)
print(url)
craw(url,i)
爬取结果:
分析:关键是正则表达式的运用和爬取思想的熟悉。
PS:以上代码和思想来自《精通Python网络爬虫 核心技术、框架与项目实战 ,韦玮》有需要的小伙伴可以私聊我,share with you!一起学习