当当网书籍封面爬取

当当网书籍封面爬取

       本人小白一枚,才开始接触爬虫,这是第一次进行爬虫试验,爬取了当当网上python相关书籍的封面。至于为什么想到做这个,也是参考了别人的文章啦,没有照搬,主要还是自己的思路。

       在当当网输入python,搜索结果有57页,作为小白,首先尝试抓取出一页的封面图片。
       在网页界面右击,查看网页源代码,找到代码中的封面图片链接(只看源代码找不出或者说不确定链接在哪的话,可以右击检查,在Elements中鼠标指哪,网页中对应部分就会被标记选中)。以下代码片段包含了其中两本书的图片链接:

                       
  •  Python编程 从入门到实践

    Python编程 从入门到实践【图灵程序设计丛书】Python3.5编程入门图书 机器学习 数据处理 网络爬虫热门编程语言 从基本概念到完整项目开发 帮助零基础读者迅速掌握Python编程 附赠源代码文件

    上到有编程基础的程序员,下到10岁少年,想入门Python并达到可以开发实际项目的水平,本书是读者*! 本书是一本全面的从入门到实践的Python编程教程,带领读者快速掌握编程基础知识、编写出能解决实际问题的代码并开发复杂项目。 书中内容分为基础篇和实战篇两部分。基础篇介绍基本的编程概念,如列表、字典、类和循环,并指导读者编写整洁且易于理解的代码。另外还介绍了如何让程序能够与用户交互,以及如何在代码运行前进行测试。实战篇介绍如何利用新学到的知识开发功能丰富的项目:2D游戏《外星人入侵》,数据可视化实战,Web应用程序。

    ¥62.00定价:¥89.00 (6.97折)

    60044条评论

    [美]埃里克·马瑟斯Eric Matthes /2016-07-01 /人民邮电出版社

  •                             
  •  Python学习手册(原书第5版)

    Python学习手册(原书第5版)Python入门必读之作,位列美亚软件编程畅销榜首,《Python编程》姊妹篇 覆盖Python 3.3和Python 2.7两个版本,详细讲解各种语言特性,并新增大量示例

    本书根据Python专家Mark Lutz的著名培训课程编写而成,是易于掌握和自学的Python语言教程。书中以目前主流的Python 3.X为主,同时兼顾Python 2.X的内容,全面、系统讲解Python语言核心知识,每个知识都会以知识点、思想、示例代码的方式详细展开,由浅入深,循序渐进。同时每章都配有章后习题、编程练习及详尽的解答,并且还配有大量注释、示例和图表,便于你学习新的技能和巩固加深自己的理解。无论你从事哪个领域,本书都为你提供了未来全部Python工作的必备知识。

    ¥173.00定价:¥219.00 (7.9折)

    113条评论

    [美]马克·卢茨 /2018-11-05 /机械工业出版社

  • 图片链接所在的位置为:
    http://img3m0.ddimg.cn/67/4/24003310-1_b_7.jpg’ alt=’ Python编程 从入门到实践’ />
    http://img3m8.ddimg.cn/27/32/25576578-1_b_5.jpg’ src=‘images/model/guan/url_none.png’ alt=’ Python学习手册(原书第5版)’ />

    在网页上观察后,进入python开始写代码啦~~

    第一页的URL为http://search.dangdang.com/?key=python&act=input&page_index=1

    import requests
    url=r'http://search.dangdang.com/?key=python&act=input&page_index=1'
    response=requests.get(url)
    text=response.text
    text
    

           得到的 text 即为之前在网页看到的源代码。可以观察出的规律是,图片的链接均在这样的格式中,用正则式匹配一下:

    import re
    re.findall("",text)
    len(re.findall("",text))
    

           一页有60本书的信息,匹配出了65项,查看匹配成功的部分,其中多余的5项为:





           我们真正需要的那60项可以更准确表示为这样的格式,而多余的5项中没有 jpg,不具备这样的格式,所以正则式改为:

    fit=re.findall("",text)
    len(fit)
    

    检测一下列表 fit 有60个元素。
    现在 fit 中的元素形如以下两个例子:

    ’
    ’

           还需要进一步提取出 http 开头的链接,同时提取出 alt 后面的书名。创建列表 links 和 names,遍历 fit 中的元素,将提取出的链接和书名添加到列表中。

    links=[]
    names=[]
    for i in fit:
        links.append(re.findall("http.*?jpg",i))
        name=re.findall("alt.*'",i)
        name=re.sub("^alt=' ","",name[0])
        name=re.sub("'$","",name)
        names.append(name)
    

           可以检查一下,links 和 names 均有60个元素,是预期的结果。接下来就是同时遍历 links 和 names,下载获取每一张图片,以书名保存下来就OK了~编写了如下的代码:

    for i in range(len(links)):
        print("Downloding the Picture of "+names[i]+" from: "+links[i][0])
        pic=requests.get(links[i][0])
        file=open(names[i]+".jpg","xb") #一定要事先创建一个文件夹,并一定记得指定为默认工作目录!!!图片将保存到文件夹里。否则,上千张图片将占据你原来的工作目录。。。。。。
        file.write(pic.content)
        file.close()
    

           我的默认工作目录为桌面,某次调试不小心运行完以上代码,大量图片在电脑桌面疯狂生长。。。。。。所以要记得事先创建好文件夹,将默认工作目录改为这个文件夹呀(真诚的语气)

    当当网书籍封面爬取_第1张图片
           运行代码,我创建的 pic 文件夹里就有60张图片了,按时间排下序,图片的顺序就和网页上一样了。

    当当网书籍封面爬取_第2张图片
    接下来实现爬取57页的封面图片。首先观察每一页的URL的规律:

    http://search.dangdang.com/?key=python&act=input&page_index=1
    http://search.dangdang.com/?key=python&act=input&page_index=2
                                                           ⋮ \vdots
    http://search.dangdang.com/?key=python&act=input&page_index=57

           每一页唯一的不同就在于 page_index 后面跟的数字,所以用一个循环遍历每个数字,做一个字符串拼接就可以了。代码中还添加了一个 n,用于做每一页匹配个数的监测。运行后可以看到1至56页匹配个数为60,57页匹配个数为9,与预期结果相符。

    links=[]
    names=[]
    n=[]
    print("Loading...")
    for i in range(57):
        url=r'http://search.dangdang.com/?key=python&act=input&page_index='+str(i+1)
        response=requests.get(url)
        text=response.text
        fit=re.findall("",text)
        n.append(len(fit))
        for i in fit:
            links.append(re.findall("http.*?jpg",i))
            name=re.findall("alt.*'",i)
            name=re.sub("^alt=' ","",name[0])
            name=re.sub("'$","",name)
            names.append(name)
    

    len(links)
    Out[53]: 3369
    len(names)
    Out[54]: 3369

    有3369条书籍信息

           共57页的图书链接和书名均已保存在 links 和 names 列表里,接下来根据链接地址下载图片保存的代码和处理一页是一样的,运行一下。

    for i in range(len(links)):
        print("Downloding the Picture of "+names[i]+" from: "+links[i][0])
        pic=requests.get(links[i][0])
        file=open(names[i]+".jpg","xb")
        file.write(pic.content)
        file.close()
    

           似乎运行了以后爬虫就完成了,然而数据多了总会出点问题的。没多久,就出现了第一次报错:

    File “”, line 4, in
    file=open(names[i]+".jpg",“xb”)
    FileExistsError: [Errno 17] File exists: ‘Python深度学习.jpg’

           FileExistsError 的意思是文件已存在错误。因为我打开文件(file=open())时用的是创建写模式(‘x’),即文件不存在则创建,存在则返回异常 FileExistsError,所以书名重复时就会报错。在这里我更改了打开模式,改成覆盖写模式(‘w’),即文件不存在则创建,存在则覆盖原有文件(书名重了按理说封面应该是一样的吧)。关于文件的打开模式,可以参考这里。

    file=open(names[i]+".jpg",“xb”)
                           ↓ \downarrow
    file=open(names[i]+".jpg",“wb”)

           再运行,又出现报错OSError,原因是书名中带有 *,open 时就会报错(页面越往后提取出的书名包含了很多杂乱的内容。。。我还没考虑怎么处理的事,就先这样了)。就简单处理了一下,将 * 替换成空格,就不会报错了。之后调试还发现,’|’,’?’ 也会导致这种报错,还有成对的 ‘:’,均替换成空格。
           也就是在运行上一段代码之前,再加上一段:

    for i in range(len(names)):
        names[i]=re.sub("[\*\|:\?]"," ",names[i])
    

           又一次运行,又有新的报错 FileNotFoundError,按理说改为覆盖写模式是不会出现这种错误的,看了一下导致报错的书名,其中有符号 ‘/’,这个符号会在表示文件路径中出现,比较特殊,所以以某种原因导致了打开文件时出错吧,至于怎么清楚地解释,我还没深究,反正替换成空格就可以继续跑了。。。

    File “”, line 4, in
    file=open(names[i]+".jpg",“wb”)
    FileNotFoundError: [Errno 2] No such file or directory: ‘Python基础教程 第2版 编程从入门到实践 核心语言开发指南 自学教程基础书籍 程序设计/软件开发教材 代码大全入.jpg’

           终于,没有报错了。查看一下,用于监测每一页匹配数量的列表 n 的最后一个数字变成了7(之前调试时是9),links 和 names 的元素个数也从3369变成3367,也就是从调试到现在,网页上 python 相关书目的条数发生了变化。

    print(n[56],len(links),len(names))
    7 3367 3367

           其实,网页上的内容经常都在发生变化,我昨天晚上写好了爬虫代码,调试不报错了,今天来写这篇 record 时,用昨天的正则式就多匹配出来两项,这里的正则式是今天又小改了一下的。所以,我的爬虫初体验就是,具体问题具体分析,很灵活多变的。
           最后,展示一下下载好的图片吧~~~网页上书目条数是3367,因为是覆盖写,最后保存的图片是3025张。

    当当网书籍封面爬取_第3张图片
    附上完整的代码:

    import time
    start=time.perf_counter()
    import requests
    import re
    links=[]
    names=[]
    n=[]
    response_time=0
    print("Loading...")
    for i in range(57):
        url=r'http://search.dangdang.com/?key=python&act=input&page_index='+str(i+1)
        t0=time.perf_counter()
        response=requests.get(url)
        t1=time.perf_counter()
        response_time=response_time+t1-t0
        text=response.text
        fit=re.findall("",text)
        n.append(len(fit))
        for i in fit:
            links.append(re.findall("http.*?jpg",i))
            name=re.findall("alt.*'",i)
            name=re.sub("^alt=' ","",name[0])
            name=re.sub("'$","",name)
            names.append(name)
    for i in range(len(names)):
        names[i]=re.sub("[\*/\|:\?]"," ",names[i])
    t0=time.perf_counter()
    for i in range(len(links)):
        print("Downloding the Picture of "+names[i]+" from: "+links[i][0])
        pic=requests.get(links[i][0])
        file=open(names[i]+".jpg","wb")
        file.write(pic.content)
        file.close()
    t1=time.perf_counter()
    download_time=t1-t0
    end=time.perf_counter()
    print("所有图片已下载完成!")
    print("请求响应总时间:{}s".format(response_time))
    print("图片下载时间:{}s".format(download_time))
    print("运行时间:{}s".format(end-start))
    

           加了个时间监测,requests.get 向网页发出请求到响应的总耗时为26s,向3367张图片的 HTTP 发出请求后响应、并保存的总耗时为120s,程序的总运行时间149s。
    当当网书籍封面爬取_第4张图片

    你可能感兴趣的:(当当网书籍封面爬取)