一.结构

上面的这张图是Scrapy的整个结构。你可以把整个Scrapy框架看成是一家爬虫公司。最中心位置的Scrapy Engine(引擎)就是这家爬虫公司的大boss,负责统筹公司的4大部门,每个部门都只听从它的命令,并只向它汇报工作。
1.Scheduler(调度器)部门主要负责处理引擎发送过来的requests对象(即网页请求的相关信息集合,包括params,data,cookies,request headers…等),会把请求的url以有序的方式排列成队,并等待引擎来提取(功能上类似于gevent库的queue模块)。
2.Downloader(下载器)部门则是负责处理引擎发送过来的requests,进行网页爬取,并将返回的response(爬取到的内容)交给引擎。它对应的是爬虫流程【获取数据】这一步。
3.Spiders(爬虫)部门是公司的核心业务部门,主要任务是创建requests对象和接受引擎发送过来的response(Downloader部门爬取到的内容),从中解析并提取出有用的数据。它对应的是爬虫流程【解析数据】和【提取数据】这两步。
4.Item Pipeline(数据管道)部门则是公司的数据部门,只负责存储和处理Spiders部门提取到的有用数据。这个对应的是爬虫流程【存储数据】这一步。
5.Downloader Middlewares(下载中间件)的工作相当于下载器部门的秘书,比如会提前对引擎大boss发送的诸多requests做出处理。
6.Spider Middlewares(爬虫中间件)的工作则相当于爬虫部门的秘书,比如会提前接收并处理引擎大boss发送来的response,过滤掉一些重复无用的东西。

二.工作原理

上图展现出的也是Scrapy框架的工作原理——引擎是中心,其他组成部分由引擎调度。
在Scrapy里,整个爬虫程序的流程都不需要我们去操心,且Scrapy中的程序全部都是异步模式,所有的请求或返回的响应都由引擎自动分配去处理。

三.代码实现

需求 : 爬取豆瓣Top250图书信息

1.创建项目(MAC版)

首先要安装 Scrapy库,参考Pycham安装第三方模块
PyCharm中打开Terminal ,输入指令 “scrapy startproject module”,其中module为模块名,看到如下的信息表示成功创建scrapy项目:

参考 : PyCharm创建Scrapy项目
创建之后的结构 :

2.编辑爬虫

spiders是放置爬虫的目录。我们可以在spiders这个文件夹里创建爬虫文件。我们来把这个文件,命名为top250。后面的大部分代码都需要在这个top250.py文件里编写。放置位置如下:

爬虫基本结构 :

import scrapy
import bs4
from ..items import DoubanItem

class DoubanSpider(scrapy.Spider):
#定义一个爬虫类DoubanSpider,继承自scrapy.Spider类。
    name = 'douban'
    #定义爬虫的名字为douban。这个名字是爬虫的唯一标识。name = 'douban'意思是定义爬虫的名字为douban。等会我们启动爬虫的时候,要用到这个名字。
    allowed_domains = ['book.douban.com']
    #定义爬虫爬取网址的域名。:`allowed_domains`是定义允许爬虫爬取的网址域名(不需要加https://)。如果网址的域名不在这个列表里,就会被过滤掉。
    #为什么会有这个设置呢?当你在爬取大量数据时,经常是从一个URL开始爬取,然后关联爬取更多的网页。
    #比如,假设我们今天的爬虫目标不是爬书籍信息,而是要爬豆瓣top250,每本书的书评。我们会先爬取书单,再找到每本书的URL,再进入每本书的详情页面去抓取评论。
    #`allowed_domains就限制了,我们这种关联爬取的URL,一定在book.douban.com这个域名之下,不会跳转到某个奇怪的广告页面。`
    start_urls = []
    #start_urls是定义起始网址,就是爬虫从哪个网址开始抓取。在此,allowed_domains的设定对start_urls里的网址不会有影响。
    for x in range(3):
        url = 'https://book.douban.com/top250?start=' + str(x * 25)
        start_urls.append(url)
        #把豆瓣Top250图书的前3页网址添加进start_urls。

    def parse(self, response):
    #parse是默认处理response的方法,中文意思是解析。
        bs = bs4.BeautifulSoup(response.text,'html.parser')
        #用BeautifulSoup解析response。
        datas = bs.find_all('tr',class_="item")
        #用find_all提取元素,这个元素里含有书籍信息。
        for data in  datas:
        #遍历data。
            title = data.find_all('a')[1]['title']
            #提取出书名。
            publish = data.find('p',class_='pl').text
            #提取出出版信息。
            score = data.find('span',class_='rating_nums').text
            #提取出评分。
            print([title,publish,score])
            #打印上述信息。

3.定义数据
我们要爬取的数据是书名、出版信息和评分,我们来看看如何在items.py里定义这些数据。
import scrapy
#导入scrapy
class DoubanItem(scrapy.Item):
#定义一个类DoubanItem,它继承自scrapy.Item
#这样,有许多好用属性和方法,就能够直接使用。比如到后面,引擎能将item类的对象发给Item Pipeline(数据管道)处理。
    title = scrapy.Field()
    #定义书名的数据属性
    publish = scrapy.Field()
    #定义出版信息的数据属性
    score = scrapy.Field()
    #定义评分的数据属性
    #定义了书名、出版信息和评分三种数据。scrapy.Field()这行代码实现的是,让数据能以类似字典的形式记录。

你会看到打印出来的结果的确和字典非常相像,但它却并不是dict,它的数据类型是我们定义的DoubanItem,属于“自定义的Python字典”。我们可以利用类似上述代码的样式,去重新写top250.py。如下所示:

from scrapy import Spider
import bs4
from ..items import DoubanItem
# 需要引用DoubanItem,它在items里面。因为是items在top250.py的上一级目录,所以要用..items,这是一个固定用法。

class DoubanSpider(Spider):
#定义一个爬虫类DoubanSpider。
    name = 'douban'
    #定义爬虫的名字为douban。
    allowed_domains = ['book.douban.com']
    #定义爬虫爬取网址的域名。
    start_urls = []
    #定义起始网址。
    for x in range(3):
        url = 'https://book.douban.com/top250?start=' + str(x * 25)
        start_urls.append(url)
        #把豆瓣Top250图书的前3页网址添加进start_urls。

    def parse(self, response):
    #parse是默认处理response的方法。
        bs = bs4.BeautifulSoup(response.text,'html.parser')
        #用BeautifulSoup解析response。
        datas = bs.find_all('tr',class_="item")
        #用find_all提取元素,这个元素里含有书籍信息。
        for data in  datas:
        #遍历data。
            item = DoubanItem()
            #实例化DoubanItem这个类。
            item['title'] = data.find_all('a')[1]['title']
            #提取出书名,并把这个数据放回DoubanItem类的title属性里。
            item['publish'] = data.find('p',class_='pl').text
            #提取出出版信息,并把这个数据放回DoubanItem类的publish里。
            item['score'] = data.find('span',class_='rating_nums').text
            #提取出评分,并把这个数据放回DoubanItem类的score属性里。
            print(item['title'])
            #打印书名。
            yield item
            #yield item是把获得的item传递给引擎。

当我们每一次,要记录数据的时候,比如前面在每一个最小循环里,都要记录“书名”,“出版信息”,“评分”。我们会实例化一个item对象,利用这个对象来记录数据。
每一次,当数据完成记录,它会离开spiders,来到Scrapy Engine(引擎),引擎将它送入Item Pipeline(数据管道)处理。这里,要用到yield语句。
yield可以简单理解为:它有点类似return,不过它和return不同的点在于,它不会结束函数,且能多次返回信息。

如果用可视化的方式来呈现程序运行的过程,就如同上图所示:爬虫(Spiders)会把豆瓣的10个网址封装成requests对象,引擎会从爬虫(Spiders)里提取出requests对象,再交给调度器(Scheduler),让调度器把这些requests对象排序处理。
然后引擎再把经过调度器处理的requests对象发给下载器(Downloader),下载器会立马按照引擎的命令爬取,并把response返回给引擎。
紧接着引擎就会把response发回给爬虫(Spiders),这时爬虫会启动默认的处理response的parse方法,解析和提取出书籍信息的数据,使用item做记录,返回给引擎。引擎将它送入Item Pipeline(数据管道)处理。
请注意DoubanItem 属性赋值的写法,千万不要用.来访问
4.设置
到这里,我们就用代码编写好了一个爬虫。不过,实际运行的话,可能还是会报错。
原因在于Scrapy里的默认设置没被修改。点击settings.py文件
①.USER _AGENT的注释取消(删除#),然后替换掉user-agent的内容,修改请求头。
②.遵守robots协议换成无需遵从robots协议
把ROBOTSTXT_OBEY=True改成ROBOTSTXT_OBEY=False
5.保存数据
①.存储成csv文件
在settings.py文件里,添加如下的代码 :
FEED_URI='./storage/data/%(name)s.csv'
FEED_FORMAT='CSV'
FEED_EXPORT_ENCODING='ansi'

FEED_URI是导出文件的路径。'./storage/data/%(name)s.csv',就是把存储的文件放到与settings.py文件同级的storage文件夹的data子文件夹里。
FEED_FORMAT 是导出数据格式,写CSV就能得到CSV格式。
FEED_EXPORT_ENCODING 是导出文件编码,ansi是一种在windows上的编码格式,你也可以把它变成utf-8用在mac电脑上。

②.存储成Excel文件

先在setting.py里设置启用ITEM_PIPELINES,设置方法如下:

#需要修改`ITEM_PIPELINES`的设置代码:

# Configure item pipelines
# See https://doc.scrapy.org/en/latest/topics/item-pipeline.html
ITEM_PIPELINES = {
     'jobuitest.pipelines.JobuitestPipeline': 300,
 }

只要取消ITEM_PIPELINES的注释(删掉#)即可。
编辑pipelines.py文件。存储为Excel文件,我们依旧是用openpyxl模块来实现,代码如下,注意阅读注释:

import openpyxl

class JobuiPipeline(object):
#定义一个JobuiPipeline类,负责处理item
    def __init__(self):
    #初始化函数 当类实例化时这个方法会自启动
        self.wb =openpyxl.Workbook()
        #创建工作薄
        self.ws = self.wb.active
        #定位活动表
        self.ws.append(['公司', '职位', '地址', '招聘信息'])
        #用append函数往表格添加表头
        
    def process_item(self, item, spider):
    #process_item是默认的处理item的方法,就像parse是默认处理response的方法
        line = [item['company'], item['position'], item['address'], item['detail']]
        #把公司名称、职位名称、工作地点和招聘要求都写成列表的形式,赋值给line
        self.ws.append(line)
        #用append函数把公司名称、职位名称、工作地点和招聘要求的数据都添加进表格
        return item
        #将item丢回给引擎,如果后面还有这个item需要经过的itempipeline,引擎会自己调度

    def close_spider(self, spider):
    #close_spider是当爬虫结束运行时,这个方法就会执行
        self.wb.save('./jobui.xlsx')
        #保存文件
        self.wb.close()
        #关闭文件

取消DOWNLOAD_DELAY = 0这行的注释(删掉#)。DOWNLOAD_DELAY翻译成中文是下载延迟的意思,这行代码可以控制爬虫的速度。因为这个项目的爬取速度不宜过快,我们要把下载延迟的时间改成0.5秒。

6.运行

在最外层的大文件夹里新建一个main.py文件(与scrapy.cfg同级)。

我们只需要在这个main.py文件里,输入以下代码,点击运行,Scrapy的程序就会启动。

from scrapy import cmdline
#导入cmdline模块,可以实现控制终端命令行。导入了这个模块,我们就能操控终端。
cmdline.execute(['scrapy','crawl','douban'])
#用execute()方法,输入运行scrapy的命令。我们想输入运行Scrapy的代码scrapy crawl douban,就需要写成['scrapy','crawl','douban']这样。

值得一提的是,在本关卡中为了教学方便理解,先写了爬虫,再定义数据。但是,在实际项目实战中,常常顺序却是相反的——先定义数据,再写爬虫。所以,流程图应如下:

四.练习

请使用Scrapy,爬取当当网2018年图书销售榜单前3页的数据(图书名、作者和书的价格)。

项目结构如下 :

1.scaItem
import scrapy
class scaItem(scrapy.Item):
    # define the fields for your item here like:
    # name = scrapy.Field()
    bookindex = scrapy.Field()
    bookname = scrapy.Field()
    bookauthor = scrapy.Field()
    bookprice = scrapy.Field()
    pass
2.BookSpider.py
from scrapy import Spider
import bs4
from ..items import scaItem

class BookSpider(Spider):
    name = 'book'
    allowed_domains = ['http://bang.dangdang.com']
    start_urls=[]
    for i in range(1,4):
        url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-year-2018-0-1-' + str(i)
        start_urls.append(url)


    def parse(self,response):
        bs = bs4.BeautifulSoup(response.text,'html.parser')
        datas = bs.find('ul',class_ = 'bang_list clearfix bang_list_mode').find_all('li')
        for data in datas:
            item = scaItem()
            item['bookindex'] = data.find('div', class_='list_num').text
            item['bookname']= data.find('div',class_ = 'name').find('a')['title']
            item['bookname'] = data.find('div',class_ = 'publisher_info').find('a').text
            item['bookprice'] = data.find('div',class_ = 'price').find('span',class_='price_n').text
            yield item
3.ScaPipeline
import csv
class ScaPipeline(object):
    def process_item(self, item, spider):
        csv_file = open('book.csv', 'a')
        writer = csv.writer(csv_file)
        writer.writerow([item['bookindex'],item['bookname'],item['bookname'], item['bookprice']])
        print(item)
        return item
4.setting
# Crawl responsibly by identifying yourself (and your website) on the user-agent
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142'

# Obey robots.txt rules
ROBOTSTXT_OBEY = False
5.main
from scrapy import cmdline
#导入cmdline模块,可以实现控制终端命令行。导入了这个模块,我们就能操控终端。
cmdline.execute(['scrapy','crawl','book'])
#用execute()方法,输入运行scrapy的命令。我们想输入运行Scrapy的代码scrapy crawl douban,就需要写成['scrapy','crawl','douban']这样。

推荐阅读更多精彩内容

  • 2021最新爬虫教程
    爬虫框架就是一些爬虫项目的半成品,可以将些爬虫常用的功能写好。然后留下一些接口,在不同的爬虫项目当中,调用适合自己...
    印象python阅读 637评论 0赞 9
  • MySQL如何实时同步数据到ES?试试这款阿里开源的神器!
    mall项目中的商品搜索功能,一直都没有做实时数据同步。最近发现阿里巴巴开源的canal可以把MySQL中的数据实...
    码不动阅读 1,960评论 3赞 54
  • 推荐10个必学python爬虫框架,你常用的是哪个?
    实现爬虫技术的编程环境有很多种,Java、Python、C++等都可以用来爬虫。但很多人选择Python来写爬虫,...
    黑羽_692867294阅读 127评论 0赞 5
  • Python爬虫自动化,帮小姐姐解放双手!
    项目来源: 漂亮学姐因为工作需要,得根据已有的学校名单,采集它们的英文名称,描述,简称有的话也带上。共有 2740...
    爱是一道光_e5f7阅读 85评论 0赞 2
  • Python爬虫:输入公司名称,爬取企查查网站中的公司信息
    前言 本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理。 以下文...
    松鼠爱吃饼干阅读 161评论 0赞 2
评论0
赞1
1赞2赞
赞赏
下载App

{"dataManager":"[]","props":{"isServer":true,"initialState":{"global":{"done":false,"artFromType":null,"fontType":"black","modal":{"ContributeModal":false,"RewardListModal":false,"PayModal":false,"CollectionModal":false,"LikeListModal":false,"ReportModal":false,"QRCodeShareModal":false,"BookCatalogModal":false,"RewardModal":false},"ua":{"value":"Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36","isIE11":false,"earlyIE":null,"chrome":"58.0","firefox":null,"safari":null,"isMac":false},"$diamondRate":{"displayable":false,"rate":0},"readMode":"day","locale":"zh-CN","seoList":[{"comments_count":0,"public_abbr":"爬虫框架就是一些爬虫项目的半成品,可以将些爬虫常用的功能写好。然后留下一些接口,在不同的爬虫项目当中,调用适合自己...","share_image_url":"https://upload-images.jianshu.io/upload_images/19311345-3fd071d5c01cb584","slug":"66244f61164b","user":{"id":19311345,"nickname":"印象python","slug":"2a2150308f7c","avatar":"https://upload.jianshu.io/users/upload_avatars/19311345/ddf23056-19a5-467a-9575-ce17c3cae983.jpg"},"likes_count":9,"title":"2021最新爬虫教程","id":82034826,"views_count":637},{"comments_count":3,"public_abbr":"mall项目中的商品搜索功能,一直都没有做实时数据同步。最近发现阿里巴巴开源的canal可以把MySQL中的数据实...","share_image_url":"https://upload-images.jianshu.io/upload_images/23633704-b17559dd66946a0c.png","slug":"91aa28f0c375","user":{"id":23633704,"nickname":"码不动","slug":"bcef08d5551e","avatar":"https://upload.jianshu.io/users/upload_avatars/23633704/44b1ed66-2bbe-4790-ada0-40076482bf77"},"likes_count":54,"title":"MySQL如何实时同步数据到ES?试试这款阿里开源的神器!","id":79339336,"views_count":1960},{"comments_count":0,"public_abbr":"实现爬虫技术的编程环境有很多种,Java、Python、C++等都可以用来爬虫。但很多人选择Python来写爬虫,...","share_image_url":"","slug":"55abe1632c44","user":{"id":24716216,"nickname":"黑羽_692867294","slug":"270aaf625f00","avatar":"https://upload.jianshu.io/users/upload_avatars/24716216/98bdc1da-d43f-4f53-b827-8763837f3877.jpg"},"likes_count":5,"title":"推荐10个必学python爬虫框架,你常用的是哪个?","id":82611495,"views_count":127},{"comments_count":0,"public_abbr":"项目来源: 漂亮学姐因为工作需要,得根据已有的学校名单,采集它们的英文名称,描述,简称有的话也带上。共有 2740...","share_image_url":"https://upload-images.jianshu.io/upload_images/24596166-33763fa08df97784.png","slug":"6bb23622e9d5","user":{"id":24596166,"nickname":"爱是一道光_e5f7","slug":"7e41657d7c21","avatar":"https://upload.jianshu.io/users/upload_avatars/24596166/dc6d513e-c787-446a-9fad-7ebd19480c79"},"likes_count":2,"title":"Python爬虫自动化,帮小姐姐解放双手!","id":82292839,"views_count":85},{"comments_count":0,"public_abbr":"前言 本文的文字及图片来源于网络,仅供学习、交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理。 以下文...","share_image_url":"https://upload-images.jianshu.io/upload_images/24396660-e468aa9906851ae5","slug":"4eb790640856","user":{"id":24396660,"nickname":"松鼠爱吃饼干","slug":"0dcc8b077292","avatar":"https://upload.jianshu.io/users/upload_avatars/24396660/343f1f0e-254a-4bdc-8dbf-ac04193967e0.jpg"},"likes_count":2,"title":"Python爬虫:输入公司名称,爬取企查查网站中的公司信息","id":80939866,"views_count":161}]},"note":{"data":{"is_author":false,"last_updated_at":1564459422,"public_title":"爬虫精进(十二) ------ Scrapy架构","purchased":false,"liked_note":false,"comments_count":0,"free_content":"u003ch1u003e一.结构u003c/h1u003enu003cpu003eu003c/pu003eu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 366px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 52.27%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="1760" data-height="920"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-8ad62e88ed013a55.png" data-original-width="1760" data-original-height="920" data-original-format="image/png" data-original-filesize="96953"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003eu003cbru003en上面的这张图是Scrapy的整个结构。你可以把整个Scrapy框架看成是一家爬虫公司。最中心位置的Scrapy Engine(引擎)就是这家爬虫公司的大boss,负责统筹公司的4大部门,每个部门都只听从它的命令,并只向它汇报工作。u003cbru003en1.u003ccodeu003eScheduleru003c/codeu003e(调度器)部门主要负责处理引擎发送过来的requests对象(即网页请求的相关信息集合,包括params,data,cookies,request headers…等),会把请求的url以有序的方式排列成队,并等待引擎来提取(功能上类似于gevent库的queue模块)。u003cbru003en2.u003ccodeu003eDownloaderu003c/codeu003e(下载器)部门则是负责处理引擎发送过来的requests,进行网页爬取,并将返回的response(爬取到的内容)交给引擎。它对应的是爬虫流程【获取数据】这一步。u003cbru003en3.u003ccodeu003eSpidersu003c/codeu003e(爬虫)部门是公司的核心业务部门,主要任务是创建requests对象和接受引擎发送过来的response(Downloader部门爬取到的内容),从中解析并提取出有用的数据。它对应的是爬虫流程【解析数据】和【提取数据】这两步。u003cbru003en4.u003ccodeu003eItem Pipelineu003c/codeu003e(数据管道)部门则是公司的数据部门,只负责存储和处理Spiders部门提取到的有用数据。这个对应的是爬虫流程【存储数据】这一步。u003cbru003en5.u003ccodeu003eDownloader Middlewaresu003c/codeu003e(下载中间件)的工作相当于下载器部门的秘书,比如会提前对引擎大boss发送的诸多requests做出处理。u003cbru003en6.u003ccodeu003eSpider Middlewaresu003c/codeu003e(爬虫中间件)的工作则相当于爬虫部门的秘书,比如会提前接收并处理引擎大boss发送来的response,过滤掉一些重复无用的东西。u003cbru003enu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 444px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 63.3%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="1760" data-height="1114"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-aaf4b0ab34dea2c2.png" data-original-width="1760" data-original-height="1114" data-original-format="image/png" data-original-filesize="194469"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003eu003cpu003eu003c/pu003enu003ch1u003e二.工作原理u003c/h1u003enu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 1102px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 157.39000000000001%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="1760" data-height="2770"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-ebd4937fed62d626.png" data-original-width="1760" data-original-height="2770" data-original-format="image/png" data-original-filesize="485431"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003eu003cbru003enu003cpu003e上图展现出的也是Scrapy框架的工作原理——引擎是中心,其他组成部分由引擎调度。u003cbru003en在Scrapy里,整个爬虫程序的流程都不需要我们去操心,且Scrapy中的程序全部都是异步模式,所有的请求或返回的响应都由引擎自动分配去处理。u003c/pu003ennu003ch1u003e三.代码实现u003c/h1u003enu003cpu003e需求 : 爬取豆瓣Top250图书信息u003c/pu003enu003ch5u003e1.创建项目(MAC版)u003c/h5u003enu003cpu003e首先要安装 Scrapy库,参考u003ca href="/p/d0af9388b361" target="_blank"u003ePycham安装第三方模块u003c/au003eu003cbru003enPyCharm中打开Terminal ,输入指令 “scrapy startproject module”,其中module为模块名,看到如下的信息表示成功创建scrapy项目:u003cbru003enu003c/pu003eu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 660px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 46.22%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="1428" data-height="660"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-3c22c3806807ce40.png" data-original-width="1428" data-original-height="660" data-original-format="image/png" data-original-filesize="128543"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003eu003cbru003en参考 : u003ca href="https://www.jianshu.com/p/d2c8b1496949" target="_blank"u003ePyCharm创建Scrapy项目u003c/au003eu003cbru003en创建之后的结构 :u003cbru003enu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 366px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 52.27%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="1760" data-height="920"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-c03ced954a2eb54c.png" data-original-width="1760" data-original-height="920" data-original-format="image/png" data-original-filesize="174024"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003eu003cpu003eu003c/pu003enu003ch5u003e2.编辑爬虫u003c/h5u003enu003cpu003espiders是放置爬虫的目录。我们可以在spiders这个文件夹里创建爬虫文件。我们来把这个文件,命名为top250。后面的大部分代码都需要在这个top250.py文件里编写。放置位置如下:u003c/pu003enu003cbru003enu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 460px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 65.68%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="1760" data-height="1156"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-9592d4ccb09c0a9d.png" data-original-width="1760" data-original-height="1156" data-original-format="image/png" data-original-filesize="205069"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003eu003cbru003enu003cpu003e爬虫基本结构 :u003c/pu003ennu003cpreu003eu003ccodeu003eimport scrapynimport bs4nfrom ..items import DoubanItemnnclass DoubanSpider(scrapy.Spider):n#定义一个爬虫类DoubanSpider,继承自scrapy.Spider类。n name = 'douban'n #定义爬虫的名字为douban。这个名字是爬虫的唯一标识。name = 'douban'意思是定义爬虫的名字为douban。等会我们启动爬虫的时候,要用到这个名字。n allowed_domains = ['book.douban.com']n #定义爬虫爬取网址的域名。:`allowed_domains`是定义允许爬虫爬取的网址域名(不需要加https://)。如果网址的域名不在这个列表里,就会被过滤掉。n #为什么会有这个设置呢?当你在爬取大量数据时,经常是从一个URL开始爬取,然后关联爬取更多的网页。n #比如,假设我们今天的爬虫目标不是爬书籍信息,而是要爬豆瓣top250,每本书的书评。我们会先爬取书单,再找到每本书的URL,再进入每本书的详情页面去抓取评论。n #`allowed_domains就限制了,我们这种关联爬取的URL,一定在book.douban.com这个域名之下,不会跳转到某个奇怪的广告页面。`n start_urls = []n #start_urls是定义起始网址,就是爬虫从哪个网址开始抓取。在此,allowed_domains的设定对start_urls里的网址不会有影响。n for x in range(3):n url = 'https://book.douban.com/top250?start=' + str(x * 25)n start_urls.append(url)n #把豆瓣Top250图书的前3页网址添加进start_urls。nn def parse(self, response):n #parse是默认处理response的方法,中文意思是解析。n bs = bs4.BeautifulSoup(response.text,'html.parser')n #用BeautifulSoup解析response。n datas = bs.find_all('tr',class_="item")n #用find_all提取u0026lt;tr class="item"u0026gt;元素,这个元素里含有书籍信息。n for data in datas:n #遍历data。n title = data.find_all('a')[1]['title']n #提取出书名。n publish = data.find('p',class_='pl').textn #提取出出版信息。n score = data.find('span',class_='rating_nums').textn #提取出评分。n print([title,publish,score])n #打印上述信息。nu003c/codeu003eu003c/preu003enu003ch5u003e3.定义数据u003c/h5u003enu003cpu003e我们要爬取的数据是书名、出版信息和评分,我们来看看如何在items.py里定义这些数据。u003c/pu003enu003cpreu003eu003ccodeu003eimport scrapyn#导入scrapynclass DoubanItem(scrapy.Item):n#定义一个类DoubanItem,它继承自scrapy.Itemn#这样,有许多好用属性和方法,就能够直接使用。比如到后面,引擎能将item类的对象发给Item Pipeline(数据管道)处理。n title = scrapy.Field()n #定义书名的数据属性n publish = scrapy.Field()n #定义出版信息的数据属性n score = scrapy.Field()n #定义评分的数据属性n #定义了书名、出版信息和评分三种数据。scrapy.Field()这行代码实现的是,让数据能以类似字典的形式记录。nu003c/codeu003eu003c/preu003enu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 596px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 30.220000000000002%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="1972" data-height="596"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-3ffaddd7abc82631.png" data-original-width="1972" data-original-height="596" data-original-format="image/png" data-original-filesize="227364"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003eu003cbru003enu003cpu003e你会看到打印出来的结果的确和字典非常相像,但它却并不是dict,它的数据类型是我们定义的DoubanItem,属于“自定义的Python字典”。我们可以利用类似上述代码的样式,去重新写top250.py。如下所示:u003c/pu003ennu003cpreu003eu003ccodeu003efrom scrapy import Spidernimport bs4nfrom ..items import DoubanItemn# 需要引用DoubanItem,它在items里面。因为是items在top250.py的上一级目录,所以要用..items,这是一个固定用法。nnclass DoubanSpider(Spider):n#定义一个爬虫类DoubanSpider。n name = 'douban'n #定义爬虫的名字为douban。n allowed_domains = ['book.douban.com']n #定义爬虫爬取网址的域名。n start_urls = []n #定义起始网址。n for x in range(3):n url = 'https://book.douban.com/top250?start=' + str(x * 25)n start_urls.append(url)n #把豆瓣Top250图书的前3页网址添加进start_urls。nn def parse(self, response):n #parse是默认处理response的方法。n bs = bs4.BeautifulSoup(response.text,'html.parser')n #用BeautifulSoup解析response。n datas = bs.find_all('tr',class_="item")n #用find_all提取u0026lt;tr class="item"u0026gt;元素,这个元素里含有书籍信息。n for data in datas:n #遍历data。n item = DoubanItem()n #实例化DoubanItem这个类。n item['title'] = data.find_all('a')[1]['title']n #提取出书名,并把这个数据放回DoubanItem类的title属性里。n item['publish'] = data.find('p',class_='pl').textn #提取出出版信息,并把这个数据放回DoubanItem类的publish里。n item['score'] = data.find('span',class_='rating_nums').textn #提取出评分,并把这个数据放回DoubanItem类的score属性里。n print(item['title'])n #打印书名。n yield itemn #yield item是把获得的item传递给引擎。nu003c/codeu003eu003c/preu003enu003cpu003e当我们每一次,要记录数据的时候,比如前面在每一个最小循环里,都要记录“书名”,“出版信息”,“评分”。我们会实例化一个item对象,利用这个对象来记录数据。u003cbru003en每一次,当数据完成记录,它会离开spiders,来到Scrapy Engine(引擎),引擎将它送入Item Pipeline(数据管道)处理。这里,要用到yield语句。u003cbru003enyield可以简单理解为:它有点类似return,不过它和return不同的点在于,它不会结束函数,且能多次返回信息。u003cbru003enu003c/pu003eu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 444px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 63.3%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="1760" data-height="1114"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-c569f327bcaf592e.png" data-original-width="1760" data-original-height="1114" data-original-format="image/png" data-original-filesize="194469"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003eu003cbru003en如果用可视化的方式来呈现程序运行的过程,就如同上图所示:爬虫(Spiders)会把豆瓣的10个网址封装成requests对象,引擎会从爬虫(Spiders)里提取出requests对象,再交给调度器(Scheduler),让调度器把这些requests对象排序处理。u003cbru003en然后引擎再把经过调度器处理的requests对象发给下载器(Downloader),下载器会立马按照引擎的命令爬取,并把response返回给引擎。u003cbru003en紧接着引擎就会把response发回给爬虫(Spiders),这时爬虫会启动默认的处理response的parse方法,解析和提取出书籍信息的数据,使用item做记录,返回给引擎。引擎将它送入Item Pipeline(数据管道)处理。u003cbru003enu003ccodeu003e请注意DoubanItem 属性赋值的写法,千万不要用.来访问u003c/codeu003eu003cpu003eu003c/pu003enu003ch5u003e4.设置u003c/h5u003enu003cpu003e到这里,我们就用代码编写好了一个爬虫。不过,实际运行的话,可能还是会报错。u003cbru003en原因在于Scrapy里的默认设置没被修改。点击settings.py文件u003c/pu003enu003ch5u003e①.USER _AGENT的注释取消(删除#),然后替换掉user-agent的内容,修改请求头。u003c/h5u003enu003ch5u003e②.遵守robots协议换成无需遵从robots协议u003c/h5u003enu003cpu003e把ROBOTSTXT_OBEY=True改成ROBOTSTXT_OBEY=Falseu003c/pu003enu003ch5u003e5.保存数据u003c/h5u003enu003ch5u003e①.存储成csv文件u003c/h5u003enu003cpu003e在settings.py文件里,添加如下的代码 :u003c/pu003enu003cpreu003eu003ccodeu003eFEED_URI='./storage/data/%(name)s.csv'nFEED_FORMAT='CSV'nFEED_EXPORT_ENCODING='ansi'nu003c/codeu003eu003c/preu003enu003cpu003eFEED_URI是导出文件的路径。'./storage/data/%(name)s.csv',就是把存储的文件放到与settings.py文件同级的storage文件夹的data子文件夹里。u003cbru003enFEED_FORMAT 是导出数据格式,写CSV就能得到CSV格式。u003cbru003enFEED_EXPORT_ENCODING 是导出文件编码,ansi是一种在windows上的编码格式,你也可以把它变成utf-8用在mac电脑上。u003c/pu003enu003ch5u003e②.存储成Excel文件u003c/h5u003enu003cpu003e先在setting.py里设置启用ITEM_PIPELINES,设置方法如下:u003c/pu003enu003cpreu003eu003ccodeu003e#需要修改`ITEM_PIPELINES`的设置代码:nn# Configure item pipelinesn# See https://doc.scrapy.org/en/latest/topics/item-pipeline.htmlnITEM_PIPELINES = {n 'jobuitest.pipelines.JobuitestPipeline': 300,n }nu003c/codeu003eu003c/preu003enu003cpu003e只要取消ITEM_PIPELINES的注释(删掉#)即可。u003cbru003en编辑pipelines.py文件。存储为Excel文件,我们依旧是用openpyxl模块来实现,代码如下,注意阅读注释:u003c/pu003enu003cpreu003eu003ccodeu003eimport openpyxlnnclass JobuiPipeline(object):n#定义一个JobuiPipeline类,负责处理itemn def __init__(self):n #初始化函数 当类实例化时这个方法会自启动n self.wb =openpyxl.Workbook()n #创建工作薄n self.ws = self.wb.activen #定位活动表n self.ws.append(['公司', '职位', '地址', '招聘信息'])n #用append函数往表格添加表头n n def process_item(self, item, spider):n #process_item是默认的处理item的方法,就像parse是默认处理response的方法n line = [item['company'], item['position'], item['address'], item['detail']]n #把公司名称、职位名称、工作地点和招聘要求都写成列表的形式,赋值给linen self.ws.append(line)n #用append函数把公司名称、职位名称、工作地点和招聘要求的数据都添加进表格n return itemn #将item丢回给引擎,如果后面还有这个item需要经过的itempipeline,引擎会自己调度nn def close_spider(self, spider):n #close_spider是当爬虫结束运行时,这个方法就会执行n self.wb.save('./jobui.xlsx')n #保存文件n self.wb.close()n #关闭文件nu003c/codeu003eu003c/preu003enu003cpu003e取消DOWNLOAD_DELAY = 0这行的注释(删掉#)。DOWNLOAD_DELAY翻译成中文是下载延迟的意思,这行代码可以控制爬虫的速度。因为这个项目的爬取速度不宜过快,我们要把下载延迟的时间改成0.5秒。u003c/pu003enu003ch5u003e6.运行u003c/h5u003enu003cpu003e在最外层的大文件夹里新建一个main.py文件(与scrapy.cfg同级)。u003c/pu003enu003cbru003enu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 481px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 54.66%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="880" data-height="481"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-65ea444a99f51591.png" data-original-width="880" data-original-height="481" data-original-format="image/png" data-original-filesize="53662"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003eu003cbru003enu003cpu003e我们只需要在这个main.py文件里,输入以下代码,点击运行,Scrapy的程序就会启动。u003c/pu003ennu003cpreu003eu003ccodeu003efrom scrapy import cmdlinen#导入cmdline模块,可以实现控制终端命令行。导入了这个模块,我们就能操控终端。ncmdline.execute(['scrapy','crawl','douban'])n#用execute()方法,输入运行scrapy的命令。我们想输入运行Scrapy的代码scrapy crawl douban,就需要写成['scrapy','crawl','douban']这样。nu003c/codeu003eu003c/preu003enu003cpu003e值得一提的是,在本关卡中为了教学方便理解,先写了爬虫,再定义数据。但是,在实际项目实战中,常常顺序却是相反的——先定义数据,再写爬虫。所以,流程图应如下:u003c/pu003enu003cbru003enu003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 700px; max-height: 366px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 52.27%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="1760" data-height="920"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-b48279e5e2612b9a.png" data-original-width="1760" data-original-height="920" data-original-format="image/png" data-original-filesize="107459"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003enu003ch1u003e四.练习u003c/h1u003enu003cpu003e请使用Scrapy,爬取当当网2018年图书销售榜单前3页的数据(图书名、作者和书的价格)。u003cbru003enu003c/pu003enu003cpu003eu003c/pu003en项目结构如下 :u003cdiv class="image-package"u003enu003cdiv class="image-container" style="max-width: 504px; max-height: 614px;"u003enu003cdiv class="image-container-fill" style="padding-bottom: 121.83%;"u003eu003c/divu003enu003cdiv class="image-view" data-width="504" data-height="614"u003eu003cimg data-original-src="//upload-images.jianshu.io/upload_images/17787668-9707e096a27ef38d.png" data-original-width="504" data-original-height="614" data-original-format="image/png" data-original-filesize="58523"u003eu003c/divu003enu003c/divu003enu003cdiv class="image-caption"u003eu003c/divu003enu003c/divu003enu003ch5u003e1.scaItemu003c/h5u003enu003cpreu003eu003ccodeu003eimport scrapynclass scaItem(scrapy.Item):n # define the fields for your item here like:n # name = scrapy.Field()n bookindex = scrapy.Field()n bookname = scrapy.Field()n bookauthor = scrapy.Field()n bookprice = scrapy.Field()n passnu003c/codeu003eu003c/preu003enu003ch5u003e2.BookSpider.pyu003c/h5u003enu003cpreu003eu003ccodeu003efrom scrapy import Spidernimport bs4nfrom ..items import scaItemnnclass BookSpider(Spider):n name = 'book'n allowed_domains = ['http://bang.dangdang.com']n start_urls=[]n for i in range(1,4):n url = 'http://bang.dangdang.com/books/bestsellers/01.00.00.00.00.00-year-2018-0-1-' + str(i)n start_urls.append(url)nnn def parse(self,response):n bs = bs4.BeautifulSoup(response.text,'html.parser')n datas = bs.find('ul',class_ = 'bang_list clearfix bang_list_mode').find_all('li')n for data in datas:n item = scaItem()n item['bookindex'] = data.find('div', class_='list_num').textn item['bookname']= data.find('div',class_ = 'name').find('a')['title']n item['bookname'] = data.find('div',class_ = 'publisher_info').find('a').textn item['bookprice'] = data.find('div',class_ = 'price').find('span',class_='price_n').textn yield itemnu003c/codeu003eu003c/preu003enu003ch5u003e3.ScaPipelineu003c/h5u003enu003cpreu003eu003ccodeu003eimport csvnclass ScaPipeline(object):n def process_item(self, item, spider):n csv_file = open('book.csv', 'a')n writer = csv.writer(csv_file)n writer.writerow([item['bookindex'],item['bookname'],item['bookname'], item['bookprice']])n print(item)n return itemnu003c/codeu003eu003c/preu003enu003ch5u003e4.settingu003c/h5u003enu003cpreu003eu003ccodeu003e# Crawl responsibly by identifying yourself (and your website) on the user-agentnUSER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142'nn# Obey robots.txt rulesnROBOTSTXT_OBEY = Falsenu003c/codeu003eu003c/preu003enu003ch5u003e5.mainu003c/h5u003enu003cpreu003eu003ccodeu003efrom scrapy import cmdlinen#导入cmdline模块,可以实现控制终端命令行。导入了这个模块,我们就能操控终端。ncmdline.execute(['scrapy','crawl','book'])n#用execute()方法,输入运行scrapy的命令。我们想输入运行Scrapy的代码scrapy crawl douban,就需要写成['scrapy','crawl','douban']这样。nnu003c/codeu003eu003c/preu003en","voted_down":false,"rewardable":true,"show_paid_comment_tips":false,"share_image_url":"https://upload-images.jianshu.io/upload_images/17787668-8ad62e88ed013a55.png","slug":"6b5afc761c5c","user":{"liked_by_user":false,"following_count":113,"gender":2,"avatar_widget":null,"slug":"eed55531d288","intro":"专注于人工智能以及ARVR技术分享,欢迎咨询与商业合作rnrnCSDN : rn https...","likes_count":82,"nickname":"千喜Ya","badges":[],"total_fp_amount":"8442900205565363169","wordage":35190,"avatar":"https://upload.jianshu.io/users/upload_avatars/17787668/2fb4f514-745f-45c9-895f-577dff5f8e31","id":17787668,"liked_user":false},"likes_count":1,"paid_type":"free","show_ads":true,"paid_content_accessible":false,"total_fp_amount":"89000000000000000","trial_open":false,"reprintable":true,"bookmarked":false,"wordage":1151,"featured_comments_count":0,"downvotes_count":0,"wangxin_trial_open":null,"guideShow":{"new_money_time_reward_type":5,"audit_user_nickname_spliter":0,"pc_note_bottom_btn":1,"pc_like_author_guidance":0,"audit_user_background_image_spliter":0,"audit_note_spliter":0,"launch_tab":1,"include_post":0,"pc_login_guidance":1,"audit_comment_spliter":1,"pc_note_bottom_qrcode":1,"audit_user_avatar_spliter":0,"flow_ad_check_detail_button_style":0,"audit_collection_spliter":0,"pc_top_lottery_guidance":1,"subscription_guide_entry":1,"creation_muti_function_on":1,"explore_score_searcher":0,"audit_user_spliter":1,"pc_note_popup":0},"commentable":true,"total_rewards_count":0,"id":51363063,"notebook":{"name":""},"description":"一.结构 二.工作原理 上图展现出的也是Scrapy框架的工作原理——引擎是中心,其他组成部分由引擎调度。在Scrapy里,整个爬虫程序的流程都不需要我们去操心,且Scrap...","first_shared_at":1564238592,"views_count":517,"notebook_id":37288528},"baseList":{"likeList":[],"rewardList":[]},"status":"success","statusCode":0},"user":{"isLogin":false,"userInfo":{}},"comments":{"list":[],"featuredList":[]}},"initialProps":{"pageProps":{"query":{"slug":"6b5afc761c5c"}},"localeData":{"common":{"jianshu":"简书","diamond":"简书钻","totalAssets":"总资产{num}","diamondValue":" (约{num}元)","login":"登录","logout":"注销","register":"注册","on":"开","off":"关","follow":"关注","followBook":"关注连载","following":"已关注","cancelFollow":"取消关注","publish":"发布","wordage":"字数","audio":"音频","read":"阅读","reward":"赞赏","zan":"赞","comment":"评论","expand":"展开","prevPage":"上一页","nextPage":"下一页","floor":"楼","confirm":"确定","delete":"删除","report":"举报","fontSong":"宋体","fontBlack":"黑体","chs":"简体","cht":"繁体","jianChat":"简信","postRequest":"投稿请求","likeAndZan":"喜欢和赞","rewardAndPay":"赞赏和付费","home":"我的主页","markedNotes":"收藏的文章","likedNotes":"喜欢的文章","paidThings":"已购内容","wallet":"我的钱包","setting":"设置","feedback":"帮助与反馈","loading":"加载中...","needLogin":"请登录后进行操作","trialing":"文章正在审核中...","reprintTip":"禁止转载,如需转载请通过简信或评论联系作者。"},"error":{"rewardSelf":"无法打赏自己的文章哟~"},"message":{"paidNoteTip":"付费购买后才可以参与评论哦","CommentDisableTip":"作者关闭了评论功能","contentCanNotEmptyTip":"回复内容不能为空","addComment":"评论发布成功","deleteComment":"评论删除成功","likeComment":"评论点赞成功","setReadMode":"阅读模式设置成功","setFontType":"字体设置成功","setLocale":"显示语言设置成功","follow":"关注成功","cancelFollow":"取消关注成功","copySuccess":"复制代码成功"},"header":{"homePage":"首页","download":"下载APP","discover":"发现","message":"消息","reward":"赞赏支持","editNote":"编辑文章","writeNote":"写文章"},"note":{},"noteMeta":{"lastModified":"最后编辑于 ","wordage":"字数 {num}","viewsCount":"阅读 {num}"},"divider":{"selfText":"以下内容为付费内容,定价 ¥{price}","paidText":"已付费,可查看以下内容","notPaidText":"还有 {percent} 的精彩内容","modify":"点击修改"},"paidPanel":{"buyNote":"支付 ¥{price} 继续阅读","buyBook":"立即拿下 ¥{price}","freeTitle":"该作品为付费连载","freeText":"购买即可永久获取连载内的所有内容,包括将来更新的内容","paidTitle":"还没看够?拿下整部连载!","paidText":"永久获得连载内的所有内容, 包括将来更新的内容"},"book":{"last":"已是最后","lookCatalog":"查看连载目录","header":"文章来自以下连载"},"action":{"like":"{num}人点赞","collection":"收入专题","report":"举报文章"},"comment":{"allComments":"全部评论","featuredComments":"精彩评论","closed":"评论已关闭","close":"关闭评论","open":"打开评论","desc":"按时间倒序","asc":"按时间正序","disableText1":"用户已关闭评论,","disableText2":"与Ta简信交流","placeholder":"写下你的评论...","publish":"发表","create":" 添加新评论","reply":" 回复","restComments":"还有{num}条评论,","expandImage":"展开剩余{num}张图","deleteText":"确定要删除评论么?"},"collection":{"title":"被以下专题收入,发现更多相似内容","putToMyCollection":"收入我的专题"},"seoList":{"title":"推荐阅读","more":"更多精彩内容"},"sideList":{"title":"推荐阅读"},"wxShareModal":{"desc":"打开微信“扫一扫”,打开网页后点击屏幕右上角分享按钮"},"bookChapterModal":{"try":"试读","toggle":"切换顺序"},"collectionModal":{"title":"收入到我管理的专题","search":"搜索我管理的专题","newCollection":"新建专题","create":"创建","nothingFound":"未找到相关专题","loadMore":"展开查看更多"},"contributeModal":{"search":"搜索专题投稿","newCollection":"新建专题","addNewOne":"去新建一个","nothingFound":"未找到相关专题","loadMore":"展开查看更多","managed":"我管理的专题","recommend":"推荐专题"},"QRCodeShow":{"payTitle":"微信扫码支付","payText":"支付金额"},"rewardModal":{"title":"给作者送糖","custom":"自定义","placeholder":"给Ta留言...","choose":"选择支付方式","balance":"简书余额","tooltip":"网站该功能暂时下线,如需使用,请到简书App操作","confirm":"确认支付","success":"赞赏成功"},"payModal":{"payBook":"购买连载","payNote":"购买文章","promotion":"优惠券","promotionFetching":"优惠券获取中...","noPromotion":"无可用优惠券","promotionNum":"{num}张可用","noUsePromotion":"不使用优惠券","validPromotion":"可用优惠券","invalidPromotion":"不可用优惠券","total":"支付总额","tip1":"· 你将购买的商品为虚拟内容服务,购买后不支持退订、转让、退换,请斟酌确认。","tip2":"· 购买后可在“已购内容”中查看和使用。","success":"购买成功"},"reportModal":{"ad":"广告及垃圾信息","plagiarism":"抄袭或未授权转载","placeholder":"写下举报的详情情况(选填)","success":"举报成功"},"guidModal":{"modalAText":"相似文章推荐","subText":"下载简书APP,浏览更多相似文章","btnAText":"先不下载,下次再说","followOkText":"关注作者成功!","followTextTip":"下载简书APP,作者更多精彩内容更新及时提醒!","followBtn":"下次再说","downloadTipText":"更多精彩内容下载简书APP","footerDownLoadText":"下载简书APP","modabTitle":"免费送你2次抽奖机会","modalbTip":"你有很大概率抽取AirPods Pro","modalbFooterTip":"下载简书APP,天天参与抽大奖","modalReward":"抽奖","scanQrtip":"扫码下载简书APP","downloadAppText":"下载简书APP,随时随地发现和创作内容","redText":"阅读","likesText":"赞","downLoadLeft":"下载App"}},"currentLocale":"zh-CN","asPath":"/p/6b5afc761c5c"}},"page":"/p/[slug]","query":{"slug":"6b5afc761c5c"},"buildId":"ZJP8vj8XvQ-o-3nKSjb0s","assetPrefix":"https://cdn2.jianshu.io/shakespeare"}


文章来源于互联网:爬虫精进(十二) —— Scrapy架构

发表评论