博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Scrapy实战-爬取豆瓣漫画
阅读量:6256 次
发布时间:2019-06-22

本文共 6046 字,大约阅读时间需要 20 分钟。

背景知识

(一)什么是Scrapy呢?Python上优秀的爬虫框架。什么是爬虫?可以看我的,也可以自行谷歌百度。

(二)建议看下的事前准备安装Scrapy。

(三)Selectors根据XPath和CSS表达式从网页中选择数据。XPath和CSS表达式是什么东西,我们不用太过于纠结,只需要知道可以使用它们在网页中选择数据。用法:利用chrome去复制所需数据的位置信息。当然进阶的话可以看

img_46205828fae95b6ca40e39a04d8e68ec.png
右击
img_c0dfa612dcd016b936e4b9dec7fea842.png
拷贝
基本用法与说明:

  • response.selector.xpath('//title/text()')##用xpath选取了title的文字内容
  • response.selector.css('title::text') ##用css选取了title的文字内容
    由于selector.xpath和selector.css使用比较普遍,所以专门定义了xpath和css,所以上面也可以写成:
  • response.xpath('//title/text()')
  • response.css('title::text')
    由于<code>.xpath</code>和<code>.css</code>返回的都是<class 'scrapy.selector.unified.SelectorList'>,因此可以这样写<code>response.css('img').xpath('@src').extract()</code>
  • 提取全部内容: .extract(),获得是一个列表
  • 提取第一个:.extract_first(),获得是一个字符串
  • 选取链接: .response.css('base::attr(href)').response.xpath('//base/@href')

正式开始

1. 新建工程 scrapy startproject tutorial

2. 创建爬虫 scrapy genspider -t basic douban douban.com

上面两步会创建如下的目录结构:

img_31a52a29a33297d600664911e3e54b68.png
Scrapy目录树

简单说下每一个文件的作用,虽然在初识Scrapy已经说过了。

  1. spiders文件夹存放你的爬虫,
  2. items.py用于定义存放网页数据的item。
  3. middlewares.py是后加的,目前不需要
  4. pipelines.py 用于处理从spiders返回的item,比如说清洗、存储。
  5. settings.py是全局设定,比如说接下来提到的DEFAULT_REQUEST_HEADERA和USER_AGENT都在这里。

3. 修改settings.py

因为Scrapy非常诚实,爬取网页的时候会表明自己是一只爬虫,但是豆瓣不给这些表明身份的爬虫活路。所以我们只能换个身份。

第一步:chrome用快捷键F12打开开发者工具,选择Network一栏,可能需要F5刷新页面:

img_4ee01d6bb17c5e9a134cf670eb5a5c3c.png
开发者工具之Network

第二步:在上图红框部分随机选取一个,会出现下图:

img_73fef0cd60fb7efd5c81faaa4b510e92.png
浏览器信息

我们主要需要的是里面红框的Request Headers的信息。

第三步:在settings.py中修改DEFAULT_REQUEST_HEADERA和USER_AGENT。

img_44e80722fb0e573061e104e48f8976da.png
settings.py
里面的USER_AGENT填写浏览器图中的User-Agent对应信息,DEFAULT_REQUEST_HEADERA里的信息根据字典的写法,从浏览器信息图中依次对应对应填上去。
PS:
顺便启用DOWNLOAD_DELAY=3减慢爬取速度,不要给别人的服务器增加太多压力。
此外启用
ITEM_PIPELINES = { 'tutorial.pipelines.DoubanPipeline': 300,}用于处理数据

4. 用爬虫的视角看网页,

在命令行中输入scrapy shell https://movie.douban.com/chart 这时候会进入scrapy版的ipython,输入view(response)就可以查看网页。

5. 定义要爬取的内容

在items.py中作如下修改

import scrapyclass DoubanItem(scrapy.Item):    # define the fields for your item here like:    # name = scrapy.Field()    title = scrapy.Field()    link = scrapy.Field()    info = scrapy.Field()    desc = scrapy.Field()

6. 单页逻辑

爬取多个网页前,我们首先得要成功提取一个网页的信息。在spiders/douban.py做如下修改

# -- coding: utf-8 --
import scrapy
from scrapy.http import Request
from ..items import DoubanItem

class DoubanSpider(scrapy.Spider):    name = "douban"    allowed_domains = ["douban.com"]    start_urls = (        'https://book.douban.com/tag/%E6%BC%AB%E7%94%BB?start=0&type=T',    )    def parse(self, response):        item = DoubanItem()        for sel in response.css('#subject_list > ul > li > div.info'):            item['title']= sel.css('h2 > a::text').extract_first()            item['link'] = sel.css('h2 > a::attr(href)').extract_first()            item['info'] = sel.css('div.pub::text').extract_first()            item['desc'] = sel.css('p::text').extract_first()            yield item

大致的爬虫就完成了。用scrapy crawl douban开始工作。由于scrap构建在python2.7上,所以对中文支持不太好,在命令行中会以unicode编码的方式显示,所以在shell上看到一堆不认识的\xxx也不要太担心。

7.数据储存

为了方便之后调用数据,我们需要用pipelines.py将爬取的数据存储在固定的文件中。可以用json等格式储存,也可以存放在数据库中。网页爬取数据往往不太规范,建议使用mongodb(NoSQL)。

import jsonimport codecsImport pymongo #python中用来操作mongodb的库##存储为json格式class DoubanPipeline(object):    def __init__(self):        self.file = codecs.open('douban_movie.json','wb',encoding='utf-8')    def process_item(self, item, spider):        line = json.dumps(dict(item)) + '\n'        self.file.write(line.decode("unicode_escape"))        return itemclass MongoPipeline(object):    collection_name = 'douban_cartoon' # mongo的collection相当于sql的table    def __init__(self, mongo_uri,mongo_db):        self.mongo_uri = mongo_uri        self.mongo_db = mongo_db    ## 配置mongo    @classmethod    def from_crawler(cls, crawler):        return cls(            mongo_uri=crawler.settings.get('MONGO_URI'), #从settings中mongo的uri            mongo_db=crawler.settings.get('MONGO_DATABASE','douban') #从settings中获取数据库,默认为douban        )    # 在spider工作开始前连接mongodb    def open_spider(self, spider):        self.client = pymongo.MongoClient(self.mongo_uri)        self.db = self.client[self.mongo_db]    ## 在spider工作结束后关闭连接    def close_spider(self, spider):        self.client.close()    ## 在mongodb中插入数据    def process_item(self, item, spider):        # for i in item:        self.db[self.collection_name].insert(dict(item))        return item

运行后就可以在项目所在目录找到douban_movie.json,mongodb的话需要自己去查询了。

多页逻辑(一)

我们需要在这一页获取下一个的链接,然后重新调用parse函数爬取这个链接。

def parse(self, response):        .....        ## 获取下一个的链接        href = response.xpath('//*[@id="subject_list"]/div[2]/span[4]/a')        url = u'https://book.douban.com'+ href.css('a::attr(href)').extract_first()        yield Request(url, callback=self.parse)

多页逻辑(二)

我们还可以通过Scrapy提供的CrawlSpider完成多页爬取。CrawlSpider比Spider多了一步即设置Rule,具体可以看我的[Scrapy基础之详解Spider]的CrawlSpider。

第一步shell试错

为了确保LinkExtractor能提取到正确的链接,我们需要在shell中进行试验。

scrapy shell https://book.douban.com/tag/漫画 from scrapy.linkextractors import LinkExtractor ##导入LinkExtractor item=LinkExtractor(allow='/tag/漫画',restrict_xpaths=('//*[@id="subject_list"]/div[2]/span/a')).extract_links(response) ##需要反复修改

第二步修改爬虫

修改后的爬虫如下:

# -- coding: utf-8 --
import scrapy
from scrapy.linkextractors import LinkExtractor
from scrapy.spiders import CrawlSpider, Rule
from tutorial.items import DoubanItem

class ManhuaSpider(CrawlSpider):    name = 'manhua'    allowed_domains = ['book.douban.com']    start_urls = ['https://book.douban.com/tag/漫画']    rules = (        Rule(LinkExtractor(allow=r'/tag/漫画',                           restrict_xpaths=('//*[@id="subject_list"]/div[2]/span/a')),             callback='parse_item',             follow=True),    )    def parse_item(self, response):        item = DoubanItem()        for sel in response.css('#subject_list > ul > li > div.info'):            item['title']= sel.css('h2 > a::text').extract_first()            item['link'] = sel.css('h2 > a::attr(href)').extract_first()            item['info'] = sel.css('div.pub::text').extract_first()            item['desc'] = sel.css('p::text').extract_first()            yield item

运行结果和多页逻辑(一)的一致。


进一步,你可以看,在这个的基础上增加图片下载功能。

如果怕被ban,可以看


本文参考了的,

,以及最重要的官方文档。


写在最后:

网络上有那么多的Scrapy的教程,为啥我还要写一个呢?因为我觉得真正学会用自己语言去表达一门技术的时候,才算入门了。
还有写出来的东西才能让别人发现自己的不足,希望各位大大批评指正。
我的源代码托管在上,有需要的话可以去看

转载地址:http://hexsa.baihongyu.com/

你可能感兴趣的文章
ogg 、 Shareplex和DSG RealSync 对比
查看>>
NK3C程序配置
查看>>
webrtc中APM(AudioProcessing module)的使用2
查看>>
lunix的查看Tomcat目录下日志的快速操作
查看>>
zabbix添加邮件报警机制
查看>>
微信开放之模板消息
查看>>
Hql 中实用查询时候 引号的使用
查看>>
利用PowerShell复制SQLServer账户的所有权限
查看>>
SQLServer 维护脚本分享(10)索引
查看>>
js里父页面与子页面的相互调用
查看>>
AES加解密【示例】
查看>>
jdbc向各种数据库发送sql语句
查看>>
比特币进一步学习-针对作弊问题的处理
查看>>
Android实现手机摄像头的自动对焦
查看>>
ASCII流程图
查看>>
Linux知识积累(5) 关机shutdown和重启reboot
查看>>
HTML5为输入框添加语音输入功能
查看>>
[LeetCode] Find Permutation 找全排列
查看>>
os.environ() 说明
查看>>
Python学习札记(二十) 函数式编程1 介绍 高阶函数介绍
查看>>