一篇文章搞定 Scrapy 爬虫框架

发布时间:2020-10-18 03:40:11 作者:马哥教育
来源:网络 阅读:551

                                                                                        Scrapy框架

Scrapy是用Python实现的一个为了爬取网站数据,提取结构性数据而编写的应用框架。可以应用在包括数据挖掘、信息处理或存储历史数据等一系列的程序中。

Scrapy使用Twisted基于事件的高效异步网络框架来处理网络通信,可以加快下载速度,不用自己去实现异步框架,并且包含了各种中间件接口,可以灵活的完成各种需求。

Scrapy架构

一篇文章搞定 Scrapy 爬虫框架

Scrapy Engine

调度器(Scheduler)

下载器(Downloader)

Spiders爬虫

Spider是编写的类,作用如下:

Item Pipeline

以下是item pipeline的一些典型应用:

下载器中间件(Downloader middlewares)

简单讲就是自定义扩展下载功能的组件。

   它提供了一个简便的机制,通过插入自定义代码来扩展Scrapy功能

Spider中间件(Spider middlewares)

Spider中间件,是在引擎和Spider之间的特定钩子(specific hook),处理spider的输入(response)和输出(items或requests)。

也提供了同样的简便机制,通过插入自定义代码来扩展Scrapy功能。

数据流(Data flow)

1.引擎打开一个网站(open a domain),找到处理该网站的Spider并向该spider请求第一个(批)要爬取的URL(s)

2.引擎从Spider中获取到第一个要爬取的URL并加入到调度器(Scheduler)作为请求以备调度

3.引擎向调度器请求下一个要爬取的URL

4.调度器返回下一个要爬取的URL给引擎,引擎将URL通过下载中间件并转发给下载器(Downloader)

5.一旦页面下载完毕,下载器生成一个该页面的Response,并将其通过下载中间件发送给引 擎

6.引擎从下载器中接收到Response,然后通过Spider中间件发送给Spider处理

7.Spider处理Response并返回提取到的Item及(跟进的)新的Request给引擎

8.引擎将Spider返回的Item交给Item Pipeline,将Spider返回的Request交给调度器

9.(从第二步)重复执行,直到调度器中没有待处理的request,引擎关闭

注意:

只有当调度器中没有任何request了,整个程序才会停止执行。如果有下载失败的URL,会重新下载

安装scrapy

  $ pip install wheel

  $ pip install scrapy

  $ pip install Twisted-18.4.0-cp35-cp35m-win_amd64.whl

windows下出现如下问题:

copying src\twisted\words\xish\xpathparser.g -> build\lib.win-amd64-3.5\twisted\words\xish running build_ext building 'twisted.test.raiser' extension error: Microsoft Visual C++ 14.0 is required. Get it with "Microsoft Visual C++ Build Tools": http://landinghub.visualstudio.com/visual-cpp-build-tools解决方案是,下载编译好的twisted,Python Extension Packages for Windowspython3.5 下载 Twisted-18.4.0-cp35-cp35m-win_amd64.whlpython3.6 下载 Twisted-18.4.0-cp36-cp36m-win_amd64.whl安装twisted$ pip install Twisted-18.4.0-cp35-cp35m-win_amd64.whl之后在安装scrapy就没有什么问题了

安装好,使用scrapy命令看看

  1.> scrapy  2.Scrapy 1.5.0 - no active project  3.  4.Usage:  5. scrapy <command> [options] [args]  6.  7.Available commands:  8.bench Run    quick benchmark test  9.check       Check spider contracts  10.crawl       Run a spider  11.edit       Edit spider  12.fetch       Fetch a URL using the Scrapy downloader  13.genspider     Generate new spider using pre-defined templates  14.list       List available spiders  15.parse       Parse URL (using its spider) and print the results  16.runspider     Run a self-contained spider (without creating a project)  17.settings     Get settings values  18.shell       Interactive scraping console  19.startproject   Create new project  20.version     Print Scrapy version  21.view       Open URL in browser, as seen by Scrapy

                                                     Scrapy开发

项目编写流程

1.创建项目

  使用 scrapy startproject proname 创建一个scrapy项目

  scrapy startproject <project_name> [project_dir]

2.编写item

  在items.py中编写Item类,明确从response中提取的item

3.编写爬虫

  编写spiders/proname_spider.py,即爬取网站的spider并提取出item

4.编写item pipeline

  item的处理,可以存储

1 创建项目

1.1 豆瓣书评爬取

标签为“编程”,第一页、第二页链接:

https://book.douban.com/tag/%E7%BC%96%E7%A8%8B?start=0&type=T

https://book.douban.com/tag/%E7%BC%96%E7%A8%8B?start=20&type=T

随便找一个目录来创建项目,执行下面命令

$ scrapy startproject first .

会产生如下目录和文件

first ├─ scrapy.cfg └─ first   ├─ items.py   ├─ middlewares.py   ├─ pipelines.py   ├─ settings.py   ├─ __init__.py   └─ spiders     └─ __init__.py

  外部的first目录是整个项目目录,内部的first目录是整个项目的全局目录

  必须有的重要的项目的配置文件

  'firstscrapy.pipelines.FirstscrapyPipeline': 300item交给哪一个管道处理,300 越小优先  

   级越高

   ITEM_PIPELINES 管道配置

  'first.middlewares.FirstDownloaderMiddleware': 543543 越小优先级越高

  __init__.py 必须有,可以在这里写爬虫类,也可以写爬虫子模块

1.# first/settings.py参考2.BOT_NAME = 'first'3.SPIDER_MODULES = ['first.spiders']4.NEWSPIDER_MODULE = 'first.spiders'5.6.USER_AGENT = "Mozilla/5.0 (Windows NT 6.1)AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.75 Safari/537.36"7.ROBOTSTXT_OBEY = False8.9.DOWNLOAD_DELAY = 310.11.# Disable cookies (enabled by default)12.COOKIES_ENABLED = False

注意一定要更改User-Agent,否则访问https://book.douban.com/会返回403

2 编写Item

  1.在items.py中编写  2.import scrapy  3.class BookItem(scrapy.Item):  4.title = scrapy.Field() # 书名  5.rate = scrapy.Field() # 评分

3 编写爬虫

为爬取豆瓣书评编写爬虫类,在spiders目录下:

  1.# scrapy源码中  2.class Spider():  3.def parse(self, response): # 解析返回的内容  4.raise NotImplementedError

爬取读书频道,tag为“编程”的书名和评分:

https://book.douban.com/tag/%E7%BC%96%E7%A8%8B?start=20&type=T

使用模板创建spider, $ scrapy genspider -t basic book https://www.douban.com/

  1.import scrapy  2.  3.class BookSpider(scrapy.Spider): # BookSpider   4.name = 'doubanbook' # 爬虫名,可修改,重要   5.allowed_domains = ['豆瓣'] # 爬虫爬取范围   6.url = '豆瓣图书标签: 编程'   7.start_urls = [url] # 起始URL   8.  9.# 下载器获取了WEB Server的response就行了,parse就是解析响应的内容   10.def parse(self, response):   11. print(type(response), '~~~~~~~~~') #scrapy.http.response.html.HtmlResponse   12.print(response)   13.print('-' * 30)

使用crawl爬取子命令

   1.$ scrapy list   2.$ scrapy crawl -h   3.scrapy crawl [options] <spider>   4.   5.指定爬虫名称开始爬取   6.$ scrapy crawl doubanbook   7.   8.可以不打印日志   9.$ scrapy crawl doubanbook --nolog

如果在windows下运行发生twisted的异常 ModuleNotFoundError: No module named 'win32api' ,请安装 $ pip install pywin32。

response是服务器端HTTP响应,它是scrapy.http.response.html.HtmlResponse类。

由此,修改代码如下

   1.import scrapy   2.from scrapy.http.response.html import HtmlResponse   3.   4.class BookSpider(scrapy.Spider): # BookSpider   5. name = 'doubanbook' # 爬虫名    6. allowed_domains = ['豆瓣'] # 爬虫爬取范围    7. url = '豆瓣图书标签: 编程'    8.start_urls = [url] # 起始URL    9.   10. # 下载器获取了WEB Server的response就行了,parse就是解析响应的内容    11.def parse(self, response:HtmlResponse):    12. print(type(response)) #scrapy.http.response.html.HtmlResponse    13. print('-'*30)    14. print(type(response.text), type(response.body))   15.print('-'*30)   16.print(response.encoding)   17.with open('o:/testbook.html', 'w', encoding='utf-8') as f:   18. try:    19. f.write(response.text)    20. f.flush()    21. except Exception as e:    22.print(e)

3.1 解析HTML

爬虫获得的内容response对象,可以使用解析库来解析。

scrapy包装了lxml,父类TextResponse类也提供了xpath方法和css方法,可以混合使用这两套接口解析HTML。

选择器参考:

https://scrapy-chs.readthedocs.io/zh_CN/0.24/topics/selectors.html#id3

  1.import scrapy  2.from scrapy.http.response.html import HtmlResponse  3.  4.response = HtmlResponse('file:///O:/testbook.html', encoding='utf-8') # 构造对象  5.  6.with open('o:/testbook.html', encoding='utf8') as f:   7.response._set_body(f.read()) # 填充数据   8.#print(response.text)
  9.  1O.# 获取所有标题及评分  11.# xpath解析   12.subjects = response.xpath('//li[@class="subject-item"]')   13.for subject in subjects:   14.title = subject.xpath('.//h3/a/text()').extract() # list   15.print(title[0].strip())  16.   17.rate = subject.xpath('.//span[@class="rating_nums"]/text()').extract()  18.print(rate[0].strip())   19.  2O.print('-'*30)   21.# css解析   22.subjects = response.css('li.subject-item')   23.for subject in subjects:   24.title = subject.css('h3 a::text').extract()   25.print(title[0].strip())   26.  27.rate = subject.css('span.rating_nums::text').extract()   28.print(rate[0].strip())   29.print('-'*30)  30.   31. # xpath和css混合使用、正则表达式匹配   32.subjects = response.css('li.subject-item')   33.for subject in subjects:  34.# 提取链接  35.href =subject.xpath('.//h3').css('a::attr(href)').extract()  36.print(href[0])  37.  38. # 使用正则表达式  39.id = subject.xpath('.//h3/a/@href').re(r'\d*99\d*')  40.if id:   41.print(id[0])   42.  43.# 要求显示9分以上数据   44.rate = subject.xpath('.//span[@class="rating_nums"]/text()').re(r'^9.*')   45.# rate = subject.css('span.rating_nums::text').re(r'^9\..*')   46.if rate:   47.print(rate)

3.2 item封装数据

   1.# spiders/bookspider.py   2.import scrapy   3.from scrapy.http.response.html import HtmlResponse   4.from ..items import BookItem   5.   6.class BookSpider(scrapy.Spider): # BookSpider   7.name = 'doubanbook' # 爬虫名    8.allowed_domains = ['豆瓣'] # 爬虫爬取范围    9.url = '豆瓣图书标签: 编程'   10.start_urls = [url] # 起始URL   11.   12. # 下载器获取了WEB Server的response就行了,parse就是解析响应的内容    13.def parse(self, response:HtmlResponse):    14.items = []    15.# xpath解析    16.subjects = response.xpath('//li[@class="subject-item"]')    17.for subject in subjects:    18.title = subject.xpath('.//h3/a/text()').extract()        19.rate = subject.xpath('.//span[@class="rating_nums"]/text()').extract_first()        20.item = BookItem()        21.item['title'] = title[0].strip()        22.item['rate'] = rate.strip()        23. items.append(item)   24.     25. print(items)   26.   27.return items # 一定要return,否则保存不下来   28.    29.# 使用命令保存return的数据   30.# scrapy crawl -h   31.# --output=FILE, -o FILE dump scraped items into FILE (use - for stdout)   32.# 文件扩展名支持'json', 'jsonlines', 'jl', 'csv', 'xml', 'marshal', 'pickle'   33.# scrapy crawl doubanbook -o dbbooks.json

得到下图数

一篇文章搞定 Scrapy 爬虫框架

注意上图的数据已经是unicode字符,汉字的unicode表达。

4 pipeline处理

将bookspider.py中BookSpider改成生成器,只需要把 return items 改造成 yield item ,即由产生一个列表变成yield一个个item

脚手架帮我们创建了一个pipelines.py文件和一个类

4.1 开启pipeline

  1.# Configure item pipelines  2.# See Item Pipeline - Scrapy 1.8.0 documentation  3.ITEM_PIPELINES = {  4.'first.pipelines.FirstPipeline': 300,  5.}

整数300表示优先级,越小越高。

取值范围为0-1000

4.2常用方法

一篇文章搞定 Scrapy 爬虫框架

   1.class FirstPipeline(object):    2.def __init__(self): # 全局设置    3. print('~~~~~~~~~~ init ~~~~~~~~~~~~')    4.    5.def open_spider(self, spider): # 当某spider开启时调用    6. print(spider,'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~')    7.   8.def process_item(self, item, spider):    9. # item 获取的item;spider 获取该item的spider    10.return item    11.   12.def close_spider(self, spider): # 当某spider关闭时调用    13.print(spider,'========================================')   14.

需求

通过pipeline将爬取的数据存入json文件中

   1.# spider/bookspider.py   2.import scrapy   3.from scrapy.http.response.html import HtmlResponse   4.from ..items import BookItem   5.   6.class BookSpider(scrapy.Spider): # BookSpider   7. name = 'doubanbook' # 爬虫名    8. allowed_domains = ['豆瓣'] # 爬虫爬取范围    9.url = '豆瓣图书标签: 编程'    10. start_urls = [url] # 起始URL   11.   12.# spider上自定义配置信息    13.custom_settings = {    14. 'filename' : 'o:/books.json'   15. }   16.# 下载器获取了WEB Server的response就行了,parse就是解析响应的内容   17.def parse(self, response:HtmlResponse):   18. #items = []    19.# xpath解析    20.subjects = response.xpath('//li[@class="subject-item"]')    21.for subject in subjects:   22.title = subject.xpath('.//h3/a/text()').extract()    23.rate =subject.xpath('.//span[@class="rating_nums"]/text()').extract_first()    24.item = BookItem()    25.item['title'] = title[0].strip()    26.item['rate'] = rate.strip()    27.#items.append(item)   28.   29.yield item    30.#return items   31.   32.# pipelines.py
   33.import simplejson as json
   34.
   35.class FirstPipeline(object):    36. def __init__(self): # 全局设置    37. print('~~~~~~~~~~ init ~~~~~~~~~~~~')   38.   39.def open_spider(self, spider): # 当某spider开启时调用    40. print('{} ~~~~~~~~~~~~~~~~~~~~'.format(spider))    41. print(spider.settings.get('filename'))    42.self.file = open(spider.settings['filename'], 'w', encoding='utf-8')    43.self.file.write('[\n')   44.    45.def process_item(self, item, spider):    46.# item 获取的item;spider 获取该item的spider    47.self.file.write(json.dumps(dict(item)) + ',\n')    48.return item   49.   50.def close_spider(self, spider): # 当某spider关闭时调用   51.self.file.write(']')    52.self.file.close()    53.print('{} ======================='.format(spider))    54.print('-'*30)

5 url提取

如果要爬取下一页内容,可以自己分析每一页的页码变化,也可以通过提取分页栏的链接

   1.# spider/bookspider.py   2.import scrapy   3.from scrapy.http.response.html import HtmlResponse   4.from ..items import BookItem   5.   6.class BookSpider(scrapy.Spider): # BookSpider    7.name = 'doubanbook' # 爬虫名   8.allowed_domains = ['豆瓣'] # 爬虫爬取范围   9.url = '豆瓣图书标签: 编程'    10.start_urls = [url] # 起始URL   11.   12.# spider上自定义配置信息    13.custom_settings = {      14.'filename' : 'o:/books.json'   15.}   16.   17.# 下载器获取了WEB Server的response就行了,parse就是解析响应的内容      18.def parse(self, response:HtmlResponse):    19.#items = []      20.# xpath解析      21.# 获取下一页,只是测试,所以使用re来控制页码    22.print('-' * 30)   23.urls = response.xpath('//div[@class="paginator"]/span[@class="next"]/a/@href').re(   24.          r'.*start=[24]\d[^\d].*')    25.print(urls)   26.print('-' * 30)   27.yield from (scrapy.Request(response.urljoin(url)) for url in urls)      28.print('++++++++++++++++++++++++')   29.    30.subjects = response.xpath('//li[@class="subject-item"]')    31.for subject in subjects:   32.# 解决图书副标题拼接    33.title = "".join(map(lambda x:x.strip(), subject.xpath('.//h3/a//text()').extract()))    34.rate = subject.xpath('.//span[@class="rating_nums"]/text()').extract_first()    35.#print(rate) # 有的没有评分,要注意可能返回None   36.   37.item = BookItem()   38.item['title'] = title   39.item['rate'] = rate    40.#items.append(item)    41.yield item   42.    43.#return items

一篇文章搞定 Scrapy 爬虫框架

推荐阅读:
  1. 一篇文章带你了解网络爬虫的概念及其工作原理
  2. 一篇文章教会你理解Scrapy网络爬虫框架的工作原理和数据采集过程

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

python开发 python运维自动化 python运维

上一篇:微信小程序swiper组件用法实例分析【附源码下载】

下一篇:由Python编写的MySQL管理工具代码实例

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》