scrapy框架的简单使用——爬取当当网图书信息

**

Scrapy爬取当当网图书信息实例 ——以警察局办案为类比

**

使用Scrapy进行信息爬取的过程看起来十分的复杂,但是他的操作方式与警局办案十分的相似,那么接下来我们就以故事的形式开始Scrapy爬取当当网的实例。在开始之前呢,我们先在你常用的磁盘目录下新建一个文件夹以存放爬虫(那么我是建在E:/Dangdang这一文件之下)。

那么,故事现在开始。有一天,E省(E盘)Dangdang市(Dangdang文件夹)Scrapy警局接到了一起报案,根据群众的举报信息,Scrapy警局将该起案件定性为特大刑事案件。于是警局立刻对该事件进行了立案,代号“dangdang”。而这个任务被分配给了警局内的精英小队demo,该小队在接取任务之后迅速的对案件进行了勘察,确定了犯罪活动的范围。在对该范围内常住人群进行筛选后,最终确定了犯罪名单实施了抓捕。

由上述故事,我们可以看到整个事件的流程,将其整理我们可以得到:

流程图
那么根据这个流程我们可以开始我们的当当网爬虫的编写

一.立案

首先,让我们打开命令提示符(windows键+r,在跳出来的框框中输入cmd回车,下简称cmd)。在cmd中进入我们要存放这个爬虫的路径,因为我建的文件在E:/Dangdang,所以我输入的是

   ->e:
   ->cd Dangdang

在这里插入图片描述

(在上述的故事中,这个过程相当于告诉我们的系统,这个案件是发生在哪个省市)

接着我们正式开始立案,在命令行中输入 ->Scrapy startproject dangdang(这个命令的作用就是在该文件下创建Scrapy爬虫所需要的各种文件。据我猜测,警察局在立案的过程中要填写一系列文件,而这些要填写的文件就相当于刚刚生成的这些文件)
在这里插入图片描述

二.分配任务

在立案完成之后我们要进行任务的分配,我们知道警察局有很多的案件要处理,不可能每个人都参与到同一个案件的调查中,所以我们要将这些任务分配给不同的部门不同的小组进行处理。在Scrapy中,这些小队的就是我们的spider。
我们使用以下的命令创建一个spider(也就是被分配到任务的小队):

 ->cd dangdang 
 //立案后,进入该案件,如果你在上面建立项目名称为yourpro,那么就cd yourpro
  ->scrapy genspider demo category.dangdang.com/cp01.49.01.00.00.00.html
  //这个命令是由scrapy警局发出的命令,genspider就是生成(generate)一个spider,spider的名字叫demo,他要对category.dangdang.com/cp01.49.01.00.00.00.html进行调查(category.dangdang.com/cp01.49.01.00.00.00.html就是你要爬取网页的域名,注意在输入这个的时候不要有http://,因为他在生成文件后会自己添加上这个前缀,如果这里也有http://,在生成文件之后会出现域名不存在的错误),我这里是选取了当当网大学教材图书的网址。

在这里插入图片描述

出现跟我上面一样的提示即创建成功。

三.确定活动范围

我们在刚刚生成的目录里找到我们的创建的spider,我的文件路径就是
E:/Dangdang/dangdang/dangdang/spiders/demo.py,我们用pycharm打开它。然后会得到这样的界面:
在这里插入图片描述
可以看到红线位置有一个allowed_domains=****和一个start_urls=*****,其中start_url的就是我们爬虫最开始工作的地方,也就是我们爬虫爬取的第一个网页,我们可以注意到,它给定的形式是一个列表,因此我们可以在这个列表里面再添加多个网址作为他的起始url(需要 的是,它生成的这个网址末尾有一个/,我们要把它去掉,网址末尾不能有/)。而allowed_domains则相当于一个限定域,它告诉这个爬虫你只能在这个范围里面爬取数据,而不能去别的地方爬取。比如allowed_domains=[‘baidu.com’]那么它就只能爬取百度的页面,而不能到搜狐的网站上去爬取数据。那么这里,我们将冒号内的网址改为’dangdang.com’,当然也可以直接用#注释掉因为这里其实并没有必要进行限定。

四.筛选嫌疑人

筛选嫌疑人就是我们对该网页中数据筛选的过程,因为我们需要的数据只是网页的一部分,所以我们要想办法将所需数据筛选出来。打开浏览器输入我们要爬取的网址(这里的浏览器比较推荐火狐的和谷歌的浏览器),按f12进入开发者工具(不同的浏览器可能会不太一样)。
在这里插入图片描述
我们可以看到红色箭头处有一个小标志(下称小标志),它可以帮助你快速的选中你需要定位的部分。如图,点击那个红色小圈圈里面的按钮,然后在页面上选取所需部分:
在这里插入图片描述
(左边选中的就是一本书的信息区域,以下称书本信息的分区,一页有60本书,就是60个分区)注意右边蓝色被选中区域,多试验几本书,我们发现每一本书的信息都在<li>标签里,注意li标签的class属性,发现第一本书就在<li class=”line1”>,第二本书就在<li class=”line2”>里,以此类推。再通过观察我们发现每一页最大为line60,那么我们可以进行代码的书写了,在这里我们要用到两种选择器css和xpath,具体的语法大家可以百度一下,这里我就提一下我们需要用到的语法,首先我们要使用css选择器将每一本书的分区给抓下来存储在一个Selector选择器中,再由xpath进行具体信息的筛选。
在这里插入图片描述
筛选的思路就是先把每一本书从页面上分开来,然后在这个页面中找到每个信息在代码中所在的位置。
那么第一步,在请求返回的response(不清楚的看一下那张scrapy的原理图)使用css选择器,下面先贴出代码:

def parse(self, response):
    for i in range(1,61):  //range(n,m,y)即从n开始计数,到m为止但不包括m,步长为y,默认为1
        lab = "line"+str(i) //由于css选择器中要输入字符类型,故构造字符串lab输出的就是line1到line60
        lab1 = "li."+lab  //css语法中对于一个标签的class属性可以用标签名.属性名的形式完成,这里输出的就是li.line1-li.line60,即li标签名中class属性为line1-line60的
        for eachbook in response.css(lab1):  //这句话就是将所有css返回的selector选择器命名为eachbook,换句话说就是筛选到的书本信息的分区,下面的筛选都是在eachbook里面进行,即在每一本书的信息分区进行
            title = eachbook.xpath('./a/@title').extract_first()    //下面详细讲
            author = eachbook.xpath('./p[@class="search_book_author"]/span/a/@title').extract_first()
            price = eachbook.xpath('./p[@class= "price"]/span[@class="search_now_price"]/text()').extract_first()

我们还是使用小标志分别选中书的标题、价格、和作者:
在这里插入图片描述
不难看出我们所需要的书名信息就在li标签下a标签的title属性里(查找的过程就像是警察在户籍系统里查找一个人一样,某某某是哪个省的人,然后在哪个市、哪个村、是干什么的)

在这里插入图片描述
同样的道理可以找出price在class名为price的标签下class名为search_now_price的标签下(注意不是标签里,而是两个标签之间的文本)。
在这里插入图片描述
作者名字在属性名为search_book_author的p标签里的span标签下a标签的title属性里。
按照上述说法我们就可以用xpath选择器在eachbook中选择我们需要的这些信息了:
title = eachbook.xpath(‘./a/text()’).extract_first()
其中./就是当前位置也就是上面css选择器选中的位置/a就相当于我们平时系统路径的下一级,也就是下一个a标签,‘/text()‘就是取上一级标签后的文本。该选择器返回的是一个包含data数值和path信息的头为Selector的列表,用exrtact_first()就是取data列表中的第一个值,如果直接是extract()就是返回一个data列表。为了防止大家听不懂我们用一个例子说明这个问题:
在这里插入图片描述
如果不加extract(),就会出现返回上述类型的列表。
在这里插入图片描述
如果加了就会返回上面的。
在这里插入图片描述
如果用extract_first()或者extract()[0]就返回上面的。

price = eachbook.xpath('./p[@class= "price"]/span[@class="search_now_price"]/text()).extract_first()

这里的@是选中的意思p[@class=”price”]就是选中class名为price的p标签,如果@后面跟一个属性名字就是选中属性的值。

 author=eachbook.xpath('./p[@class="search_book_author"]/span/a/@title').extract_first()

如上所说@title就是选中title所有的值。

五.确定抓捕名单

好了,到上面位置,我们所要抓取的罪犯(数据)已经全部分析完成,那么这个时候我们需要返回一个抓捕名单交给上级实施抓捕。

def parse(self, response):
    for i in range(1,61):
        lab = "line"+str(i)
        lab1 = "li."+lab
        for eachbook in response.css(lab1):
            title = eachbook.xpath('./a/@title').extract_first()
            author = eachbook.xpath('./p[@class="search_book_author"]/span/a/@title').extract_first()
            price = eachbook.xpath('./p[@class= "price"]/span[@class="search_now_price"]/text()').extract_first()
            yield{
                "title":title,
                "author":author,
                "price":price,
            }

我们看到这里用到了一个yield,yield是一个生成器,起作用可以参考return,那么它与return的差别是,如果使用了return那么return后面的代码将不会运行。而yield则继续运行下面的代码。我们用yield返回一个字典”title”里的数据就是上述储存在title里面的数据(这个格式就好比 姓名:,班级:,年龄:** 不过前面的字段名称还是要用引号引起来的)。
当然我们不可能只爬取一页的数据啦,那么我们到底如何实现翻页呢?
在这里插入图片描述
我们将页面下拉到最后,看到红色框框的位置,原来我们平时点击该按钮进行翻页的时候我们是点击了上面的超链接,使得我们通过该条链接进入到下一页。我们对比前三页的链接:
http://category.dangdang.com/cp01.49.01.00.00.00.html
http://category.dangdang.com/pg2-cp01.49.01.00.00.00.html
http://category.dangdang.com/pg3-cp01.49.01.00.00.00.html
就是在http://category.dangdang.com的基础上添加了红色横线部分的链接。

next_url = response.css('div.paging li.next a::attr(href)').extract_first()
print(next_url)
if next_url:
    url = response.urljoin(next_url)
    yield Request(url,callback=self.parse)

那么我们可以先使用css选择器选中横线部分的链接,怎么选的就不再具体讲了。其中a::attr(href)就是选中a标签的href属性。因为如果翻到最后一页next_url可能为空,所以用if语句进行判断,如果next_url不是空,就在现有的url后面添加上next_url的内容形成新的url(这里用到了urljoin,它可以从urllib.parse中导入)。最后用Request(url,callback=self.parse)返回新的url请求,并重新调用self的parse函数进行多页面的爬取。
这里附上完整的代码:

     # -*- coding: utf-8 -*-
import scrapy
from urllib.parse import urljoin
from scrapy.http import Request


class DemoSpider(scrapy.Spider):
    name = 'demo'
    allowed_domains = ['dangdang.com']
    start_urls = ['http://category.dangdang.com/cp01.49.01.00.00.00.html']

    def parse(self, response):
        for i in range(1,61):
            lab = "line"+str(i)
            lab1 = "li."+lab
            for eachbook in response.css(lab1):
                title = eachbook.xpath('./a/@title').extract_first()
                author = eachbook.xpath('./p[@class="search_book_author"]/span/a/@title').extract_first()
                price = eachbook.xpath('./p[@class= "price"]/span[@class="search_now_price"]/text()').extract_first()
                yield{
                    "title":title,
                    "author":author,
                    "price":price,
                }

        next_url = response.css('div.paging li.next a::attr(href)').extract_first()
        print(next_url)
        if next_url:
            url = response.urljoin(next_url)
            yield Request(url,callback=self.parse)

Ctrl+S保存代码

六.收网

激动人心的时候终于到了,我们打开cmd,也可以用pycharm自带的Terminal进行操作(视图->工具窗口->terminal)进入到项目存放的路径,我的是E:/Dangdang/dangdang。然后输入scrapy crawl demo (这里的demo是你的爬虫的名字,看上面代码中name后面的值),然后刷~刷一大串数据就出来了,超激动的有没有!!!!!!
如果你要保存成csv文件的话你可以在刚刚运行代码的后面加上几个字母like this—>scrapy crawl demo -o yourdir.csv就可以在你的项目目录下生成名为yourdir.csv的文件啦!!!

在这里插入图片描述

Tips:如果你在命令行中输入scrapy提示不是内部或外部命令,你就去找找你的python下载在哪个文件夹下面,在里面找一个Scripts的文件夹加入到环境变量中即可解决。如有疑问或者说错的地方欢迎联系我。另外警察是不是这样办案我也不太清楚,如果有错嘴下留情。

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值