Scrapy 抓取网页数据

2018/6/15 posted in  Python

Scrapy 介绍

Scrapy,Python开发的一个快速、高层次的屏幕抓取和web抓取框架,用于抓取web站点并从页面中提取结构化的数据。Scrapy用途广泛,可以用于数据挖掘、监测和自动化测试。
Scrapy吸引人的地方在于它是一个框架,任何人都可以根据需求方便的修改。它也提供了多种类型爬虫的基类,如BaseSpider、sitemap爬虫等,最新版本又提供了web2.0爬虫的支持。
Scrap,是碎片的意思,这个Python的爬虫框架叫Scrapy。

首先必须有python的环境,如果没有的话需要安装,目前python2.x已经不再更新,我使用的是python3的环境。

如果你已经有了python3的环境并且已经安装了pip3,那么安装scrapy只需要一行命令即可。

pip3 install scrapy

如果你还没有安装pip3的话,建议先安装pip3进行包管理。

pip3

pip 是 Python 包管理工具,该工具提供了对Python 包的查找、下载、安装、卸载的功能。
Python 2.7.9 + 或 Python 3.4+ 以上版本都自带 pip 工具。
你可以通过以下命令来判断是否已安装:

pip --version

如果你还未安装,则可以使用以下方法来安装:

$ curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py   # 下载安装脚本
$ sudo python get-pip.py    # 运行安装脚本

注意:用哪个版本的 Python 运行安装脚本,pip 就被关联到哪个版本,如果是 Python3 则执行以下命令:

$ sudo python3 get-pip.py    # 运行安装脚本。

一般情况 pip 对应的是 Python 2.7,pip3 对应的是 Python 3.x。

>>>pip3  -h#查看pip3的命令
Commands:
  install                     Install packages.
  download                    Download packages.
  uninstall                   Uninstall packages.
  freeze                      Output installed packages in requirements format.
  list                        List installed packages.
  show                        Show information about installed packages.
  check                       Verify installed packages have compatible dependencies.
  config                      Manage local and global configuration.
  search                      Search PyPI for packages.
  wheel                       Build wheels from your requirements.
  hash                        Compute hashes of package archives.
  completion                  A helper command used for command completion.
  help                        Show help for commands.

比较常用的就是install,list,一个是安装某个框架,另一个是列出所有安装的python框架。

demo 抓取豆瓣前250名的电影

新建scrapy项目

  1. scrapy startproject 项目名称
  2. cd 进入到项目名称
  3. cd 进入到 spiders
  4. scrapy genspider xxx_spider 域名 #生成爬虫类
    • 比如scrapy genspider douban_spider movie.douban.com

项目目录如下

  • douban
    • spiders
      • douban_spider.py #最重要的爬虫类
    • items.py #爬取的model类
    • middlewares.py #中间件 伪装useragent或者设置代理
    • pipelines.py #管道类 数据同步
    • settings.py #设置类 里面有一些项目的配置

运行项目

有两种方法

  1. 打开命令行工具 scrapy crawl xxx_spider
  2. 建议使用scrapy的cmdline工具

    • 在spiders文件夹下新建入口main.py

      from scrapy import cmdline
      cmdline.execute('scrapy crawl baidubaike_spider'.split())
      

      每次从这里面运行.py就行了,不需要每次都进到特定目录运行termianl终端程序。

主要爬虫类

douban_spider.py

# -*- coding: utf-8 -*-
import scrapy

class DoubanSpiderSpider(scrapy.Spider):
    name = 'douban_spider'#爬虫名
    allowed_domains = ['movie.douban.com']
    start_urls = ['https://movie.douban.com/top250']#入口url 扔到调度器里面
    #默认的解析方法
    def parse(self, response):
    #response就是网络请求之后的响应数据
    #主要的代码解析都在这个类中进行
       pass

HTML解析器

爬取之后的数据如果为html就需要用到html解析器,业界一般有三种方式进行解析

  • Beautiifulsoup
  • 正则匹配式
  • lxml中的xpath

有人做过三个方法的比较,大致结果如下

lxml beautifulsoup re
语法难易度 简单 简单 复杂
查找速度 较快 最快

所以这里我使用的是lxml的方式进行html解析,也推荐新手从这个方式开始入门。

lxml

lxml是通过xpath来查找,使用前需使用调用ertee.HTML()方法('()'内填HTML代码)生成一个可查找的对象。

常用xpath语法如下
// 两个斜杠为向下查找孙子标签
    
/ 一个斜杠为查找直接儿子标签
    
[] 方括号内填标签属性,如查找class属性为name的a标签,格式为a[@class="name"]
    
/text() 取出标签的内容,如查找网页中的 <a class="name">KAINHUCK</a> 中的KAINHUCK,格式为//a[@class="name"]/text()
    
/@attr 取出标签的属性,如查找网页中的 <a class="name">KAINHUCK</a> 中的class属性值name,格式为//a[@class="name"]/@class 

xpath 如何提取出div下面所有标签的文本内容

有时候一个div标签下会有不同的标签,如果只是单纯的使用上面的方法,并不能提取到div下面的所有文本内容,所以xpath提供了string(.)方法。

title = html.xpath('//dd[@class="lemmaWgt-lemmaTitle-title"]/h1/text()')[0]

summary = html.xpath('//div[@class="lemma-summary"]')[0].xpath('string(.)').strip()

#strip方法返回移除字符串头尾指定的字符生成的新字符串。    

分析抓取网站的html标签

进入chrome打开开发者调试工具

另外要使用lxml的方式进行解析,可以安装插件进行查找,到chrome的商城下载xpath,这样就可以直接看到结果了,以防抓取到的标签出错。

//div[@class="article"]//ol[@class="grid_view"]/li

这段语法用于找到class为article的div标签下的class为grid_view的ol的子孙标签下的li标签。

查找出来的结果是个包含25个元素的list

代码编写

然后进入到我们的代码中,导入lxml工具,以及DoubanItem

# -*- coding: utf-8 -*-
import scrapy
from lxml import etree
from douban.items import DoubanItem


class DoubanSpiderSpider(scrapy.Spider):
    name = 'douban_spider'#爬虫名
    allowed_domains = ['movie.douban.com']
    start_urls = ['https://movie.douban.com/top250']#入口url 扔到调度器里面
    #默认的解析方法
    def parse(self, response):
        #循环电影的条目
        html = etree.HTML(response.text)
        movie_list = html.xpath('//div[@class="article"]//ol[@class="grid_view"]/li')
        for item in movie_list:
            #item文件导入
            douban_item = DoubanItem()
            #写详细的xpath 进行数据的解析
            douban_item['serial_number'] = item.xpath('.//div[@class="item"]//em/text()')[0]
            douban_item['movie_name'] = item.xpath('.//div[@class="info"]//a/span[1]/text()')[0]
            content_list = item.xpath('.//div[@class="info"]//div[@class="bd"]/p[1]/text()')
            for content in content_list:
                content_s = "".join(content.split())
                douban_item['introduce'] = content_s

            douban_item['star']= item.xpath('.//div[@class="star"]/span[@class="rating_num"]/text()')[0]
            douban_item['comment'] = item.xpath('.//div[@class="star"]/span[4]/text()')[0]
            douban_item['description'] = item.xpath('.//p[@class="quote"]/span[1]/text()')[0]
            print(douban_item)
            yield douban_item #yeild到piplines里面 进行数据清洗 数据存储
        
        #解析下一页规则 获取后一页的xpath
        next_link = html.xpath('//span[@class="next"]/link/@href')

        if next_link:
            next_link = next_link[0]
            #yeild到调度器当中 后面给了回调函数
            yield scrapy.Request('https://movie.douban.com/top250'+next_link,callback=self.parse)

其中重要的有yield方法,把我们生成的model类传输到piplines里面进行数据的存储。

还有就是因为这只是一页的数据,想要抓取的250条数据,那就要进行多次抓取,进过分析发现只需要每次把后页的a标签的href拿到就可以了,通过xpath进行解析就是

#解析下一页规则 获取后一页的xpath
        next_link = html.xpath('//span[@class="next"]/link/@href')

最好需要yeild到调度器当中,因为是部分路径,所以要先进行路径的拼接,还要指定回调函数,就是请求之后进入的回调方法。

数据导出

在spiders文件夹下新建outputdata.py

#数据导出 也可以使用terminal 直接运行
from scrapy import cmdline
#数据导出到json
# cmdline.execute('scrapy crawl douban_spider -o output.json'.split())

#数据导出到csv格式
cmdline.execute('scrapy crawl douban_spider -o output.csv'.split())