欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

scrapy初探:写一个简单的爬虫

程序员文章站 2022-05-06 20:37:48
...

outline:
0 简介
1 工程的建立:
2 简单的爬虫
3 执行爬虫
4 文件下载
5 总结

0 简介
scrapy是一个爬虫框架。
该框架能够让我们集中在爬虫的核心处理上。但是,框架带来的缺点就是不够灵活。

1 工程的建立
前提:已经安装好python以及scrapy
在cmd中,进入相应的目录,使用命令:

scrapy startproject spider_name

得到目录如下:

spider_name/
    scrapy.cfg
    spider_name/
        __init__.py
        items.py
        pipelines.py
        settings.py
        spiders/
            __init__.py
            ...

items.py:定义爬虫中的所有item。
spiders目录:要添加的代码目录。
scrapy.cfg:爬虫的配置文件。
pipelines.py:定义了爬虫的pipeline。

tips: Item是保存爬取的数据的一个容器;他的使用方法类似于python的字典。引用块内容

2 简单的爬虫
该小节写一个简单的爬虫demo。

<1> 在spiders目录里面添加一个py文件,当前定位myspider.py。这个文件就是当前爬虫的代码文件。

<2> 定义自己的Item,该Item继承自类scrapy.Item。在其中定义要保存的字段,该字段可以用scrapy.Field()初始化。该Item加载items.py中,当然也不是强制。

class MyItem(scrapy.Item):
    url = scrapy.Field()
    name = scrapy.Field()

代码中,定义了MyItem,其中要保存两个字段,一个是爬取的网页的URL,一个是爬取的网页的名字。

<3> 爬虫的主体,是要定义一个CrawlSpider的子类。这个类中定义了爬虫的动作。该类的主要属性有:
name: 定义了爬虫的名称,一个工程内,各个爬虫的名称不要重复。
allow_domains:定义了爬虫爬取网页允许的域名,是一个列表。
start_url:定义爬虫开始的URL,为一个列表。
rules:定义了爬虫遍历的链接的规则,为一个Rule类的列表。

在Rule类中,通常需要显示指定几个常用的参数:
LinkExtractor对象:接受allow,deny等参数,参数为正则表达式,表示要继续爬去的网页链接和拒绝的网页链接。
回调函数:使用字符串的形式传入回调函数的名称。不能使用parse作为回调函数,因为这个函数不能被重载。
follow参数:bool值,表示是否遍历。如果没有回调函数,该值默认为True。

另外两个中要的函数:
1> rules中的回调函数。
2 > parse_start_url: 该函数是需要改写的父类的函数。定义了在在start_url中的动作。

整个demo的代码如下:

# -*- coding -*-
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractors import LinkExtractor
from scrapy.selector import Selector
from spider.items import MyItem

class MySpider(CrawlSpider):
    name = 'MySpider'
    allow_domains = ['douban.com']
    start_urls = ['https://xxxxx.xxxxxx.com/chart/']
    rules = [Rule(LinkExtractor(allow=[r'https://xxxxx.xxxxxx.com/subject/\d+/?$']), 'parse_it', follow=True)]

    def parse_it(self, response):
        myItem = MyItem()
        myItem['url']= response.url
        myItem['name'] = response.xpath("//title/text()").extract()
        return myItem

    def parse_start_url(self, response):
        pass

这个demo中,只是简单的爬取网页的标题。在实际中,我们可以做更多的操作,比如统计网站中的数据,将网站中的图片下载下来等等。这些操作可以加载parse_start_url和parse_it这两个函数中。

3 执行爬虫
通过执行如下命令执行爬虫:

scrapy crawl MySpider

执行该命令需要进入到爬虫的目录中,第三个参数即为代码中定义的爬虫的名称。也可以将爬取的数据保存在文件中:

scrapy crawl MySpider -o items.json

每次要在命令行中切来切去的很烦,我们可以使用scrapy的cmdline, 在scrapy.cfg的同级目录下加入一个一个main.py如下,之后每次在pycharm中执行该脚本即可运行脚本。

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

cmdline.execute("scrapy crawl MySpider".split())

下面为爬取的json数据中的一部分:

[
[
{“url”: “https://xxxxx.xxxxxx.com/subject/26844922/“, “name”: [“\n \u6770\u51fa\u516c\u6c11\n”]},
{“url”: “https://xxxxx.xxxxxx.com/subject/26279289/“, “name”: [“\n \u6012\n”]},
{“url”: “https://xxxxx.xxxxxx.com/subject/25765735/“, “name”: [“\n \u91d1\u521a\u72fc3\uff1a\u6b8a\u6b7b\u4e00\u6218\n”]},
{“url”: “https://xxxxx.xxxxxx.com/subject/6873143/“, “name”: [“\n \u4e00\u6761\u72d7\u7684\u4f7f\u547d\n”]},
……
]

可以看到,爬取的内容即为Item中定义的内容。

有些网站可能使用了反爬虫机制,在这里,有一个简单的解决方法就是设置代理。在setting.py中加入设置如下:

USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_8_3) AppleWebKit/536.5 (KHTML, like Gecko) Chrome/19.0.1084.54 Safari/536.5'

4 文件下载
文件下载可以使用PIPELINE,常用的PIPELINE有FILESPIPELINE和IMAGEPIPELINE。在这个小节,以FILESPIPELINE来简单记录用法。

**一个在setting.py中,pipeline需要有两步工作:
① 在配置项中**pipeine。

ITEM_PIPELINES = {
    'spider.pipelines.MyPipeline': 3,
}

后面的数字是顺序,定义在1~1000内。

② 定义一个合法的目录。

FILES_STORE = '/pic'

这两个步骤都是必须的,一个没有配置好,就不会启动PIPELINE。

之后的工作,也就是最重要的工作就是定义PIPELINE类了。
在pipelines.py中定义自己的pipeline类,继承自类FILESPIPELINE。

在类中,主要需要实现的函数有两个。
process_item:每个item传递到pipeline中执行的操作。
item_completed:内容下载完成之后执行的操作,我们可以在这里执行重命名之类的动作。当然这个函数不是必须的,如果没有重命名的动作,下载下来的文件是以一个哈希码命名的。

下面是一个简单的demo:

class MyPipeline(FilesPipeline):
    def process_item(self, item, spider):
        for url in item["file_urls"]:
            yield Request(url)

    def item_completed(self, results, item, info):
          pass

这里的file_urls需要在MySpider类中得到。为了方便的得到url,可以使用scrapy的选择器Selector。如下面的代码得到所有img标签中src字段带有.jpg的内容。

myItem['file_urls'] = Selector(text=response.body).xpath("//img[contains(@src, '.jpg')]/@src").extract()

有的时候,我们下载不下来内容,观察输出,会发现403错误。这是因为scrapy默认是遵循roberts协议的。在settings.py中加入以下配置,表示不遵守roberts协议。

ROBOTSTXT_OBEY = False

6 总结
scrapy是一个很方便快捷的爬虫框架,使用起来,只用关注url的正则表达式和一些关键动作代码就可以实现一个完整的爬虫。但是也牺牲了一定的灵活性。

相关标签: python