Scrapy 框架 - Tung in ECNU


Scrapy 框架

Scrapy

框架结构

  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,过滤掉一些重复无用的东西。

img

创建/启动scrapy项目

项目创建

在要创建爬虫的目录下使用命令:scrapy startproject douban,douban就是Scrapy项目的名字。

之后用pycharm打开这个目录就能看到如下的文件结构

img

项目启动

项目启动有两种方式,可以使用命令行或者新建一个main.py

  1. 命令行

在本项目的根目录下使用命令scrapy crawl douban

  1. 在本项目的根目录下新建一个 main.py

cmdline模块中,有一个execute方法能执行终端的命令行,不过这个方法需要传入列表的参数。

我们想输入运行Scrapy的代码scrapy crawl douban,就需要写成['scrapy','crawl','douban']这样。

from scrapy import cmdline
#导入cmdline模块,可以实现控制终端命令行。
cmdline.execute(['scrapy','crawl','douban'])
#用execute()方法,输入运行scrapy的命令。

Spiders - 核心代码

spiders是放置爬虫的目录。我们可以在spiders这个文件夹里创建爬虫文件

import scrapybs4
from douban.items import DoubanItem

class DoubanSpider(scrapy.Spider):
    # 定义一个爬虫类DoubanSpider。
    name = 'douban'
    # 定义爬虫的名字为douban。
    allowed_domains = ['https://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提取<tr class="item">元素,这个元素里含有书籍信息。
        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

义了一个DoubanItem类。它继承自scrapy.Item类。

scrapy.Field()这行代码实现的是,让数据能以类似字典的形式记录

import scrapy

class DoubanItem(scrapy.Item):
    # 在item里面定义好我们想要的条目  分别是 title publish score
    title = scrapy.Field()
    publish = scrapy.Field()
    score = scrapy.Field()

book = DoubanItem()
# 实例化一个DoubanItem对象
book['title'] = '海边的卡夫卡'
book['publish'] = '[日] 村上春树 / 林少华 / 上海译文出版社 / 2003'
book['score'] = '8.1'
print(book)
print(type(book))

yield可以简单理解为:它有点类似return,不过它和return不同的点在于,它不会结束函数,且能多次返回信息。

scrapy.Request是构造requests对象的类。real_url是我们往requests对象里传入的每家公司招聘信息网址的参数。

callback的中文意思是回调。self.parse_job是我们新定义的parse_job方法。往requests对象里传入callback=self.parse_job这个参数后,引擎就能知道response要前往的下一站,是parse_job()方法。

Setting

  1. 设置响应头
  2.    USER_AGENT =  'Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/71.0.3578.98 Safari/537.36'
  3. 设置文件保存格式(csv 或者 excel)

FEED_URI='./storage/data/%(name)s.csv'
FEED_FORMAT='CSV'
FEED_EXPORT_ENCODING='utf-8' #按照utf-8格式编码


> 推荐csv,兼容性好且方便

3. 设置robots协议

ROBOTSTXT_OBEY = False #改成false就是不遵守规定


4. 设置下载延迟

DOWNLOAD_DELAY = 1


设置为每秒访问,减轻服务器压力



### 数据保存 

1. 使用CSV格式存储 `item` 比较容易,在`setting.py`中直接添加

FEED_URI='./storage/data/%(name)s.csv'
FEED_FORMAT='CSV'
FEED_EXPORT_ENCODING='utf-8' #按照utf-8格式编码


2. 使用EXCEL存储

1. 在setting.py中开启 ITEM_PIPELINES

2. ```python
   ITEM_PIPELINES = {
        'jobuitest.pipelines.JobuitestPipeline': 300,
   }
  1. 去编辑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()

本文链接:

https://noahtung.xyz/index.php/archives/3/
1 + 4 =
2 评论
    Noah TungChrome 76OSX
    2019年08月15日 回复
      Noah TungChrome 76OSX
      2019年08月20日 回复

      @Noah Tung 你好