API例子:用Python驱动Firefox采集网页数据

1,引言

本文讲解怎样用Python驱动Firefox浏览器写一个简易的网页数据采集器。开源Python即时网络爬虫项目将与Scrapy(基于twisted的异步网络框架)集成,所以本例将使用Scrapy采集淘宝这种含有大量ajax代码的网页数据,但是要注意本例一个严重缺陷:用Selenium加载网页的过程发生在Spider中,破坏了Scrapy的架构原则。所以,本例只是为了测试Firefox驱动和ajax网页数据采集这两个技术点,用于正式运行环境中必须予以修改,后续的文章将专门讲解修正后的实现。

请注意,本例用到的xslt文件是通过MS谋数台保存提取器后,通过API接口获得,一方面让python代码变得简洁,另一方面,节省调试采集规则的时间。详细操作请查看Python即时网络爬虫:API说明

2,具体实现
2.1,环境准备

需要执行以下步骤,准备Python开发和运行环境:

  • 安装Python–官网下载安装并部署好环境变量 (本文使用Python版本为3.5.1)
  • 安装lxml– 官网库下载对应版本的.whl文件,然后命令行界面执行 “pip install .whl文件路径”
  • 安装Scrapy–命令行界面执行 “pip install Scrapy”,详细请参考Scrapy:Python3下的第一次运行测试
  • 安装selenium–命令行界面执行 “pip install selenium”
  • 安装Firefox–官网下载安装
    上述步骤展示了两种安装:1,安装下载到本地的wheel包;2,用Python安装管理器执行远程下载和安装。
2.2,开发和测试过程

以下代码默认都是在命令行界面执行

1),创建scrapy爬虫项目simpleSpider

    E:\python-3.5.1>scrapy startproject simpleSpider

2),修改settings.py配置

有些网站会在根目录下放置一个名字为robots.txt的文件,里面声明了此网站希望爬虫遵守的规范,Scrapy默认遵守这个文件制定的规范,即ROBOTSTXT_OBEY默认值为True。在这里需要修改ROBOTSTXT_OBEY的值,找到E:\python-3.5.1\simpleSpider\simpleSpider下文件settings.py,更改ROBOTSTXT_OBEY的值为False。

3),导入API模块

在项目目录E:\python-3.5.1\simpleSpider下创建文件gooseeker.py(也可以在开源Python即时网络爬虫GitHub源 的core文件夹中直接下载),代码如下:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    # 模块名: gooseeker
    # 类名: GsExtractor
    # Version: 2.0
    # 说明: html内容提取器
    # 功能: 使用xslt作为模板,快速提取HTML DOM中的内容。
    # released by 集搜客(http://www.gooseeker.com) on May 18, 2016
    # github: https://github.com/FullerHua/jisou/core/gooseeker.py

    from urllib import request
    from urllib.parse import quote
    from lxml import etree
    import time

    class GsExtractor(object):
        def _init_(self):
            self.xslt = ""
        # 从文件读取xslt
        def setXsltFromFile(self , xsltFilePath):
            file = open(xsltFilePath , 'r' , encoding='UTF-8')
            try:
                self.xslt = file.read()
            finally:
                file.close()
        # 从字符串获得xslt
        def setXsltFromMem(self , xsltStr):
            self.xslt = xsltStr
        # 通过GooSeeker API接口获得xslt
        def setXsltFromAPI(self , APIKey , theme, middle=None, bname=None):
            apiurl = "http://www.gooseeker.com/api/getextractor?key="+ APIKey +"&theme="+quote(theme)
            if (middle):
                apiurl = apiurl + "&middle="+quote(middle)
            if (bname):
                apiurl = apiurl + "&bname="+quote(bname)
            apiconn = request.urlopen(apiurl)
            self.xslt = apiconn.read()
        # 返回当前xslt
        def getXslt(self):
            return self.xslt
        # 提取方法,入参是一个HTML DOM对象,返回是提取结果
        def extract(self , html):
            xslt_root = etree.XML(self.xslt)
            transform = etree.XSLT(xslt_root)
            result_tree = transform(html)
            return result_tree

4),创建SimpleSpider爬虫类

在项目目录E:\python-3.5.1\simpleSpider\simpleSpider\spiders下创建文件simplespider.py,代码如下:

    # -*- coding: utf-8 -*-
    import time
    import scrapy
    from lxml import etree
    from selenium import webdriver
    from gooseeker import GsExtractor

    class SimpleSpider(scrapy.Spider):
        name = "simplespider"
        allowed_domains = ["taobao.com"]
        start_urls = [
            "https://item.taobao.com/item.htm?spm=a230r.1.14.197.e2vSMY&id=44543058134&ns=1&abbucket=10"
        ]

        def __init__(self):
            # use any browser you wish
            self.browser = webdriver.Firefox()

        def getTime(self):
            # 获得当前时间戳
            current_time = str(time.time())
            m = current_time.find('.')
            current_time = current_time[0:m]
            return current_time

        def parse(self, response):
            print("start...")
            #start browser
            self.browser.get(response.url)
            #loading time interval
            time.sleep(3)
            #get xslt
            extra = GsExtractor()
            extra.setXsltFromAPI("API KEY" , "淘宝天猫_商品详情30474")
            # get doc
            html = self.browser.execute_script("return document.documentElement.outerHTML");
            doc = etree.HTML(html)
            result = extra.extract(doc)
            # out file
            file_name = 'F:/temp/淘宝天猫_商品详情30474_' + self.getTime() + '.xml'
            open(file_name,"wb").write(result)
            self.browser.close()
            print("end")   

5),启动爬虫

在E:\python-3.5.1\simpleSpider项目目录下执行命令

    E:\python-3.5.1\simpleSpider>scrapy crawl simplespider

6),输出文件

采集到的网页数据结果文件是:淘宝天猫_商品详情30474_1466064544.xml

3,展望

调用Firefox,IE等全特性浏览器显得有点太重量级,很多场合可以考虑轻量级的浏览器内核,比如,casperjs和phantomjs等。同时运行在没有界面的浏览器(headless browser,无头浏览器)模式下,也许可以对网页数据采集性能有所提升。

然后,最重要的一点是要写一个 Scrapy 的下载器,专门驱动这些浏览器采集网页数据,也就是把这个功能从Spider中迁移出来,这样才符合Scrapy的整体框架原则,实现事件驱动的工作模式。

4,相关文档
  1. Python即时网络爬虫:API说明
  2. API例子:用Java/JavaScript下载内容提取器
5,集搜客GooSeeker开源代码下载源
  1. 开源Python即时网络爬虫GitHub源
6,文档修改历史
  1. 2016-06-29:V1.0
  2. 2016-06-29:V1.1,在第一段明显位置注明本案例的缺陷
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值