爬虫之Scrapy安装及简单使用(macOS)

1.前提

1.1 使用Mac OS系统
1.2 Python3.x版本
1.3 因为mac系统自带python2.7,因此必须在终端将版本修改为python3.x版本

终端执行:

$sudo vim ~/.bash_profile

在bash_profile文件中增加下面的语句,需要安装python3时的路径:

alias python='/Library/Frameworks/Python.framework/Versions/3.6/bin/python3.6’

终端执行,使之生效:

$source ~/.bash_profile

2.安装Scrapy

Python3.6.5安装包中默认带有pip3命令,直接使用即可。

$pip3 install scrapy

注意:如果使用了pip install scrapy,则安装的scrapy将会默认搜索python2.7相关文件。这会在我们运行测试的时候报错,因为我们所有的语法和scrapy都是基于python3.x的!

终端应该输入以下内容:

$pip3 install scrapy
Collecting scrapy
  Downloading https://files.pythonhosted.org/packages/5d/12/a6197eaf97385e96fd8ec56627749a6229a9b3178ad73866a0b1fb377379/Scrapy-1.5.1-py2.py3-none-any.whl (249kB)
    100% |████████████████████████████████| 256kB 600kB/s 
Collecting pyOpenSSL (from scrapy)
  Downloading https://files.pythonhosted.org/packages/96/af/9d29e6bd40823061aea2e0574ccb2fcf72bfd6130ce53d32773ec375458c/pyOpenSSL-18.0.0-py2.py3-none-any.whl (53kB)
    100% |████████████████████████████████| 61kB 17.5MB/s 
Collecting cssselect>=0.9 (from scrapy)
  Downloading https://files.pythonhosted.org/packages/7b/44/25b7283e50585f0b4156960691d951b05d061abf4a714078393e51929b30/cssselect-1.0.3-py2.py3-none-any.whl
Collecting service-identity (from scrapy)
.
.
.
Successfully installed Automat-0.7.0 PyDispatcher-2.0.5 PyHamcrest-1.9.0 Twisted-18.9.0 asn1crypto-0.24.0 attrs-18.2.0 cffi-1.11.5 constantly-15.1.0 cryptography-2.3.1 cssselect-1.0.3 enum34-1.1.6 functools32-3.2.3.post2 hyperlink-18.0.0 idna-2.7 incremental-17.5.0 ipaddress-1.0.22 lxml-4.2.5 parsel-1.5.0 pyOpenSSL-18.0.0 pyasn1-0.4.4 pyasn1-modules-0.2.2 pycparser-2.19 queuelib-1.5.0 scrapy-1.5.1 service-identity-17.0.0 six-1.11.0 w3lib-1.19.0 zope.interface-4.5.0

默认同时安装了几个Scrapy需要依赖的包。

3.查看Scrapy

$Scrapy version
Scrapy 1.5.1

这里安装的是1.5.1版本

which Scrapy
/Library/Frameworks/Python.framework/Versions/3.6/bin/scrapy

这是安装的路径。

如果使用的是pip install scrapy,则scrapy的路径为/usr/local/bin/scrapy,默认会查找python2.7版本的包,使我们的测试失败。因为我们这里使用python3,因此这点需要特别注意。

4.创建Scrapy项目

在桌面创建了一个Demo工程

$cd Desktop
$scrapy startproject Demo

scrapy startproject:创建一个scrapy项目。

以下是项目的目录结构:

Demo/
    scrapy.cfg
    Demo/
        __init__.py
        items.py
        pipelines.py
        settings.py
        middlewares.py
        spiders/
                __init__.py
                ......

5.编写代码

使用Scrapy抓取一个网站需要四个步骤:

  1. 创建一个Scrapy项目
  2. 定义Item容器
  3. 编写爬虫
  4. 存储内容
5.1 设置抓取网站并建模

这里我们采用http://www.n360.cn网站的站点资讯资源:

97D6A079-CC2F-41AE-B50C-F42D9AA27D8B.png

我们需要抓取的是该板块的标题链接

在项目中,我们在items.py文件中建立相应的字段:

import scrapy
class DemoItem(scrapy.Item):
  #define the fields for you item here like:
  #name = scrapy.Field()
  title = scrapy.Field() #抓取的标题
  link = scrapy.Field() #抓取的链接
5.2 编写爬虫

在项目的Spider目录中,创建名为DemoSprider.py的文件,编写爬虫代码:

import scrapy

class DemoSpider(scrapy.Spider):
    # name表示爬虫的名字,在`scrapy crawl xx`时使用
    name = “demo”
    # allowed_domains定义了爬取的范围,限定在某几个域名内
    allowed_domains = ['http://www.n360.cn’]
    # start_urls定义了从哪里开始爬取
    start_urls = ['http://www.n360.cn’]

    # parse方法用于接收Downloader返回的结果
    def parse(self,response):
        with open('homepage','wb') as f:
            f.write(response.body)

这里我们接收到爬取的内容后,先写入到文件homepage中,模拟爬的过程,查看是否正确。

5.3 运行爬虫,使用终端调试
# 进入第二层的Demo目录内
$cd ~/Desktop/Demo/Demo
# 这里的demo即是我们在DemoSpider.py文件中设置的name属性
$scrapy crawl demo 

会在Demo文件夹下生成一个homepage文件,使用文本打开,会发现这就是该网站的html代码。

6.scrapy的xpath语法

抓取到html后,我们需要对html内容进行分析,传统方式是使用正则表达式。scrapy提供了几个方法,可以简化我们的操作,使查询更容易。
下面是一些基本语法:

语法 含义
/html/head/title 选择HTML文档中<head>标签内的<title>元素
/html/head/title/text() 选择上面提到的title元素的文本
//td 选择所有的<td>元素
//div[@class='mine'] 选择所有具有class='mine'属性的div元素
6.1 测试xpath语法
# 终端输入,进入scrapy shell模式
$scrapy shell "http://www.n360.cn”
# 反馈
2018-10-16 17:04:58 [scrapy.utils.log] INFO: Scrapy 1.5.1 started (bot: scrapybot)
2018-10-16 17:04:58 [scrapy.utils.log] INFO: Versions: lxml 4.2.5.0, libxml2 2.9.8, cssselect 1.0.3, parsel 1.5.0, w3lib 1.19.0, Twisted 18.9.0, Python 3.6.5 (v3.6.5:f59c0932b4, Mar 28 2018, 03:03:55) - [GCC 4.2.1 (Apple Inc. build 5666) (dot 3)], pyOpenSSL 18.0.0 (OpenSSL 1.1.0i  14 Aug 2018), cryptography 2.3.1, Platform Darwin-17.5.0-x86_64-i386-64bit
2018-10-16 17:04:58 [scrapy.crawler] INFO: Overridden settings: {'DUPEFILTER_CLASS': 'scrapy.dupefilters.BaseDupeFilter', 'LOGSTATS_INTERVAL': 0}
2018-10-16 17:04:58 [scrapy.middleware] INFO: Enabled extensions:
[‘scrapy.extensions.corestats.CoreStats’,
 ‘scrapy.extensions.telnet.TelnetConsole’,
 ‘scrapy.extensions.memusage.MemoryUsage’]
.
.
.
>>>

进入该模式后,scrapy Engine会返回给我们一个response回应,可以用它查看网页信息:

>>> response.headers
{b'Server': [b'nginx'], b'Date': [b'Tue, 16 Oct 2018 09:05:56 GMT'], b'Content-Type': [b'text/html; charset=utf-8'], b'Vary': [b'Accept-Encoding'], b'X-Powered-By': [b'PHP/5.3.29'], b'Set-Cookie': [b'PHPSESSID=nd3665jsfcp0cn7b5poc2qcfg3; path=/'], b'Content-Security-Policy': [b'upgrade-insecure-requests’]}
>>>

查询所有title:

>>> response.xpath('//title’)
[<Selector xpath='//title' data='<title>\n\n            分类目录网-网站分类目录大全,好用的网’>]
>>> 

注意,这里返回的是Selector对象,如果想得到字符串,可以使用extract()方法,extract()方法会将Selector对象转化为列表对象:

>>> response.xpath('//title').extract()
['<title>\n\n            分类目录网-网站分类目录大全,好用的网站导航\n\n        </title>’]
>>> 

这里返回的是文本列表。
如果想得到title标签的文本内容,可以使用下面的语法:

>>> response.xpath('//title/text()').extract()
['\n\n            分类目录网-网站分类目录大全,好用的网站导航\n\n        ‘]
>>> 
6.2 抓取我们的目标

通过浏览器自带的审查元素,我们知道需要的站点资讯ul元素的class属性为newslist,并且页面内没有其他与其重复,因此这可以作为关键点来抓取。

EE43F12C-91A7-4832-A63E-C2334962044E.png

>>> response.xpath("//ul[@class='newslist']").extract()
['<ul class="newslist">\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-10-09\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1800.html">\n\n                                        工业门的门洞要求及生产工艺[转载]\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-10-09\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1799.html">\n\n                                        健康公益中原行启动仪式在郑州成功举办\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-10-08\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1798.html">\n\n                                        区块链是什么?区块链+电商怎么落地呢??\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-10-07\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1796.html">\n\n                                        简述工业门的操控方式及安全性能[转载]\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-29\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1791.html">\n\n                                        西安格帆“照明空气净化器”面向全国招商\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-27\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1787.html">\n\n                                        区块链是什么?区块链+电商怎么落地呢?\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-27\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1786.html">\n\n                                        2018有哪些免费收录的分类目录站点\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-27\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1785.html">\n\n                                        分类目录网站外链还有效果吗?\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-27\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1783.html">\n\n                                        想做点小生意,coco奶茶加盟不好做?\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-25\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1775.html">\n\n                                        传统行业如何向互联网转型?\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-25\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1774.html">\n\n                                        CentOS7开放关闭防火墙与端口\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-24\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1772.html">\n\n                                        通过 CSP 指令解决https加载不了http资源问题\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-21\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1767.html">\n\n                                        区块链+电商平台设计\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-17\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1755.html">\n\n                                        windows重装系统备份还原用户凭据方法\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-14\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1752.html">\n\n                                        CentOS 7双网卡双IP内外网关配置\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-05\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1733.html">\n\n                                        linux vps修改时区设置\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-09-03\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1729.html">\n\n                                        postgresql 创建数据库 ERROR: new encoding (UTF8) is incompatible\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t\t<li>\n\n\t\t\t\t\t\t<span>\n\n                                        2018-08-31\n\n\t\t\t\t\t\t</span>\n\n\t\t\t\t\t\t<a href="/artinfo/1724.html">\n\n                                        为什么工业门要设置平衡系统?[转载]\n\n\t\t\t\t\t\t</a>\n\n\t\t\t\t\t\t</li>\n\n                                \n\t\t\t\t\t</ul>’]
>>> 

可以看到,抓到了我们想要的结果。

6.3 提取title和link
# 获取Selector对象列表,找到所有li元素的Selector对象
>>> sites = response.xpath('//ul[@class="newslist"]/li’)
>>> for site in sites:
...     title = site.xpath('a/text()').extract()
...     print(title)
... 
['\n\n                                        工业门的门洞要求及生产工艺[转载]\n\n\t\t\t\t\t\t’]
['\n\n                                        健康公益中原行启动仪式在郑州成功举办\n\n\t\t\t\t\t\t’]
['\n\n                                        区块链是什么?区块链+电商怎么落地呢??\n\n\t\t\t\t\t\t’]
['\n\n                                        简述工业门的操控方式及安全性能[转载]\n\n\t\t\t\t\t\t’]
['\n\n                                        西安格帆“照明空气净化器”面向全国招商\n\n\t\t\t\t\t\t’]
['\n\n                                        区块链是什么?区块链+电商怎么落地呢?\n\n\t\t\t\t\t\t’]
['\n\n                                        2018有哪些免费收录的分类目录站点\n\n\t\t\t\t\t\t’]
['\n\n                                        分类目录网站外链还有效果吗?\n\n\t\t\t\t\t\t’]
['\n\n                                        想做点小生意,coco奶茶加盟不好做?\n\n\t\t\t\t\t\t’]
['\n\n                                        传统行业如何向互联网转型?\n\n\t\t\t\t\t\t’]
['\n\n                                        CentOS7开放关闭防火墙与端口\n\n\t\t\t\t\t\t’]
['\n\n                                        通过 CSP 指令解决https加载不了http资源问题\n\n\t\t\t\t\t\t’]
['\n\n                                        区块链+电商平台设计\n\n\t\t\t\t\t\t’]
['\n\n                                        windows重装系统备份还原用户凭据方法\n\n\t\t\t\t\t\t’]
['\n\n                                        CentOS 7双网卡双IP内外网关配置\n\n\t\t\t\t\t\t’]
['\n\n                                        linux vps修改时区设置\n\n\t\t\t\t\t\t’]
['\n\n                                        postgresql 创建数据库 ERROR: new encoding (UTF8) is incompatible\n\n\t\t\t\t\t\t’]
['\n\n                                        为什么工业门要设置平衡系统?[转载]\n\n\t\t\t\t\t\t’]
>>> 

可以看到,获取了所有标题。

>>> for site in sites:
...     link = site.xpath('a/@href').extract()
...     print(link)
... 
['/artinfo/1800.html’]
['/artinfo/1799.html’]
['/artinfo/1798.html’]
['/artinfo/1796.html’]
['/artinfo/1791.html’]
['/artinfo/1787.html’]
['/artinfo/1786.html’]
['/artinfo/1785.html’]
['/artinfo/1783.html’]
['/artinfo/1775.html’]
['/artinfo/1774.html’]
['/artinfo/1772.html’]
['/artinfo/1767.html’]
['/artinfo/1755.html’]
['/artinfo/1752.html’]
['/artinfo/1733.html’]
['/artinfo/1729.html’]
['/artinfo/1724.html’]
>>> 

获取了所有链接。不过,这些链接都是相对路径,到代码中我们需要拼接域名。

7.代码实现

代码实现的过程,其实就是将我们在终端中的命令用代码实现一遍。

def parse(self,response):
        sites = response.xpath("//ul[@class='newslist']/li")
        for site in sites:
            title = site.xpath('a/text()').extract()
            link = site.xpath('a/@href').extract()
            print(title,link)
06D2FC39-7DCB-4158-992C-16FF7B2DE543.png

8.导入item模块


import scrapy
from Demo.items import DemoItem 

class DemoSpider(scrapy.Spider):
    # name表示爬虫的名字,在`scrapy crawl xx`时使用
    name = "demo"
    # allowed_domains定义了爬取的范围,限定在某几个域名内
    allowed_domains = ['http://www.n360.cn']
    # start_urls定义了从哪里开始爬取
    start_urls = ['http://www.n360.cn']

    # parse方法用于接受Downloader返回的结果
    def parse(self,response):
        sites = response.xpath("//ul[@class='newslist']/li")
        items = []
        for site in sites:
            item = DemoItem()
            item['title'] = site.xpath('a/text()').extract()[0]
            item['link'] = self.allowed_domains[0] + site.xpath('a/@href').extract()[0]
            items.append(item)
        return items

8.导出抓取结果

# 将parse函数返回的结果进行导出,使用json格式
$scrapy crawl demo -o items.json -t json

如果没有意外,可以看到Demo文件夹下面多了item.json文件,里面就是我们需要抓取的内容。

屏幕快照 2018-10-16 下午6.08.19.png

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容