admin 管理员组

文章数量: 1184232


2024年3月10日发(作者:金石滩旅游攻略)

或者输入s 来查看它的 header部分:

现在就像是一大堆沙子握在手里,里面藏着我们想要的金子,所以下一

步,就是用筛子摇两下,把杂质出去,选出关键的内容。

100

selector就是这样一个筛子。

在旧的版本中,Shell实例化两种selectors,一个是解析HTML的 hxs

变量,一个是解析XML 的 xxs 变量。

而现在的Shell为我们准备好的selector对象,sel,可以根据返回的

数据类型自动选择最佳的解析方案(XML or HTML)。

然后我们来捣弄一下!~

要彻底搞清楚这个问题,首先先要知道,抓到的页面到底是个什么样子。

比如,我们要抓取网页的标题,也就是这个标签:</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">可以输入:</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">[python] view plaincopy </p><p style="text-indent: 2em;font-size:18px;">1. ('//title') </p><p style="text-indent: 2em;font-size:18px;">结果就是:</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">这样就能把这个标签取出来了,用extract()和text()还可以进一步做处</p><p style="text-indent: 2em;font-size:18px;">理。</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">备注:简单的罗列一下有用的xpath路径表达式:</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">表达式</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">nodename</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">/</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">//</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">描述</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">选取此节点的所有子节点。</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">从根节点选取。</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">从匹配选择的当前节点选择文档中的节点,而不</p><p style="text-indent: 2em;font-size:18px;">101 </p><p style="text-indent: 2em;font-size:18px;">考虑它们的位置。</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">.</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">..</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">@</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">选取当前节点。</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">选取当前节点的父节点。</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">选取属性。</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">全部的实验结果如下,In[i]表示第i次实验的输入,Out[i]表示第i次结</p><p style="text-indent: 2em;font-size:18px;">果的输出(建议大家参照:W3C教程):</p><p style="text-indent: 2em;font-size:18px;"> </p><p style="text-indent: 2em;font-size:18px;">[python] view plaincopy </p><p style="text-indent: 2em;font-size:18px;">1. In [1]: ('//title') </p><p style="text-indent: 2em;font-size:18px;">2. Out[1]: [<Selector xpath='//title' data=u'<title>Open Directory - Computers:</p><p style="text-indent: 2em;font-size:18px;"> Progr'>] </p><p style="text-indent: 2em;font-size:18px;">3. </p><p style="text-indent: 2em;font-size:18px;">4. In [2]: ('//title').extract() </p><p style="text-indent: 2em;font-size:18px;">5. Out[2]: [u'<title>Open Directory - Computers: Programming: Languages: Python</p><p style="text-indent: 2em;font-size:18px;">: Books']

6.

7. In [3]: ('//title/text()')

8. Out[3]: [

Programming:'>]

9.

10. In [4]: ('//title/text()').extract()

11. Out[4]: [u'Open Directory - Computers: Programming: Languages: Python: Books

']

12.

13. In [5]: ('//title/text()').re('(w+):')

14. Out[5]: [u'Computers', u'Programming', u'Languages', u'Python']

当然title这个标签对我们来说没有太多的价值,下面我们就来真正抓

取一些有意义的东西。

使用火狐的审查元素我们可以清楚地看到,我们需要的东西如下:

102

我们可以用如下代码来抓取这个

  • 标签:

    [python] view plaincopy

    1. ('//ul/li')

  • 标签中,可以这样获取网站的描述:

    [python] view plaincopy

    1. ('//ul/li/text()').extract()

    可以这样获取网站的标题:

    [python] view plaincopy

    1. ('//ul/li/a/text()').extract()

    可以这样获取网站的超链接:

    [python] view plaincopy

    1. ('//ul/li/a/@href').extract()

    当然,前面的这些例子是直接获取属性的方法。

    我们注意到xpath返回了一个对象列表,

    那么我们也可以直接调用这个列表中对象的属性挖掘更深的节点

    (参考:

    Nesting selectors

    and

    Working with relative XPaths

    in

    the

    Selectors

    ):

    sites = ('//ul/li')

    for site in sites:

    103

    title = ('a/text()').extract()

    link = ('a/@href').extract()

    desc = ('text()').extract()

    print title, link, desc

    3.4xpath实战

    我们用shell做了这么久的实战,最后我们可以把前面学习到的内容应

    用到dmoz_spider这个爬虫中。

    在原爬虫的parse函数中做如下修改:

    [python] view plaincopy

    1. from import Spider

    2. from or import Selector

    3.

    4. class DmozSpider(Spider):

    5. name = "dmoz"

    6. allowed_domains = [""]

    7. start_urls = [

    8. "/Computers/Programming/Languages/Python/Books/",

    9. "/Computers/Programming/Languages/Python/Resource

    s/"

    10. ]

    11.

    12. def parse(self, response):

    13. sel = Selector(response)

    14. sites = ('//ul/li')

    15. for site in sites:

    16. title = ('a/text()').extract()

    17. link = ('a/@href').extract()

    18. desc = ('text()').extract()

    19. print title

    注意,我们从or中导入了Selector类,并且实例化了一

    个新的Selector对象。这样我们就可以像Shell中一样操作xpath了。

    我们来试着输入一下命令运行爬虫(在tutorial根目录里面):

    scrapy crawl dmoz

    104

    运行结果如下:

    果然,成功的抓到了所有的标题。但是好像不太对啊,怎么Top,Python

    这种导航栏也抓取出来了呢?

    我们只需要红圈中的内容:

    105

    106

    看来是我们的xpath语句有点问题,没有仅仅把我们需要的项目名称抓

    取出来,也抓了一些无辜的但是xpath语法相同的元素。

    审查元素我们发现我们需要的

      具有class='directory-url'的属性,

      那么只要把xpath语句改成

      ('//ul[@class="directory-url"]/li')即可

      107

      将xpath语句做如下调整:

      [python] view plaincopy

      1. from import Spider

      2. from or import Selector

      3.

      4. class DmozSpider(Spider):

      5. name = "dmoz"

      6. allowed_domains = [""]

      7. start_urls = [

      8. "/Computers/Programming/Languages/Python/Books/",

      9. "/Computers/Programming/Languages/Python/Resource

      s/"

      10. ]

      11.

      12. def parse(self, response):

      13. sel = Selector(response)

      14. sites = ('//ul[@class="directory-url"]/li')

      15. for site in sites:

      16. title = ('a/text()').extract()

      17. link = ('a/@href').extract()

      18. desc = ('text()').extract()

      19. print title

      成功抓出了所有的标题,绝对没有滥杀无辜:

      108

      3.5使用Item

      接下来我们来看一看如何使用Item。

      前面我们说过,Item 对象是自定义的python字典,可以使用标准字

      典语法获取某个属性的值:

      [python] view plaincopy

      1. >>> item = DmozItem()

      2. >>> item['title'] = 'Example title'

      3. >>> item['title']

      4. 'Example title'

      作为一只爬虫,Spiders希望能将其抓取的数据存放到Item对象中。

      为了返回我们抓取数据,spider的最终代码应当是这样:

      [python] view plaincopy

      1. from import Spider

      2. from or import Selector

      3.

      4. from import DmozItem

      5.

      109

      6. class DmozSpider(Spider):

      7. name = "dmoz"

      8. allowed_domains = [""]

      9. start_urls = [

      10. "/Computers/Programming/Languages/Python/Books/",

      11. "/Computers/Programming/Languages/Python/Resource

      s/"

      12. ]

      13.

      14. def parse(self, response):

      15. sel = Selector(response)

      16. sites = ('//ul[@class="directory-url"]/li')

      17. items = []

      18. for site in sites:

      19. item = DmozItem()

      20. item['title'] = ('a/text()').extract()

      21. item['link'] = ('a/@href').extract()

      22. item['desc'] = ('text()').extract()

      23. (item)

      24. return items

      4.存储内容(Pipeline)

      保存信息的最简单的方法是通过

      Feed exports

      ,主要有四种:JSON,

      JSON lines,CSV,XML。

      我们将结果用最常用的JSON导出,命令如下:

      [plain] view plaincopy

      1. scrapy crawl dmoz -o -t json

      -o 后面是导出文件名,-t 后面是导出类型。

      然后来看一下导出的结果,用文本编辑器打开json文件即可(为了方

      便显示,在item中删去了除了title之外的属性):

      110

      因为这个只是一个小型的例子,所以这样简单的处理就可以了。

      如果你想用抓取的items做更复杂的事情,你可以写一个 Item

      Pipeline(条目管道)。

      这个我们以后再慢慢玩^_^

      111


  • 本文标签: 抓取 节点 需要 爬虫 标题