如何构建基本的Web爬网程序以从网站提取信息

您是否曾经想过以编程方式从网站上捕获特定信息以进行进一步处理?说些体育成绩,股市趋势或最新时尚,比特币和其他加密货币价格?如果网站上提供了您所需的信息,则可以编写搜寻器(也称为“刮板"或“蜘蛛")来浏览网站并提取所需的内容。让我们找出如何在python中执行此操作。

请注意,有些网站不鼓励使用搜寻器来访问该网站提供的信息。因此,在任何网站上部署搜寻器之前,请先检查网站条款。

安装Scrapy

我们使用名为Scrapy的python模块来处理实际的搜寻。它快速,简单,并且可以像使用浏览器一样浏览多个网页。

但是请注意,scrapy没有在浏览网站时处理javascript的功能。因此,使用这种方法无法正确地抓取那些使用JavaScript操纵用户界面的网站和应用。

现在让我们安装scrapy。我们使用virtualenv安装scrapy。这使我们可以在目录中安装scrapy,而不会影响其他系统安装的模块。

创建目录并在该目录中初始化虚拟环境。

mkdir crawlercd crawlervirtualenv venv. venv/bin/activate

您现在可以在其中安装scrapy目录。

pip install scrapy

检查是否正确安装了scrapy。

scrapy# printsScrapy 1.4.0 - no active projectUsage:  scrapy <command> [options] [args]Available commands:  bench         Run quick benchmark test  fetch         Fetch a URL using the Scrapy downloader  genspider     Generate new spider using pre-defined templates  runspider     Run a self-contained spider (without creating a project)...

构建网站爬网程序(也称为蜘蛛)

现在让我们为加载一些信息。我们首先从https://en.wikipedia.org/wiki/Battery_(electricity)电池上的Wikipedia页面上获取一些信息。

编写搜寻器的第一步是定义一个python从 scrapy.Spider 扩展的类。让我们将此类称为 spider1

蜘蛛类至少需要满足以下条件:

  • 一个名称“ Wikipedia"
  • 一个 start_urls 变量,其中包含要开始爬网的URL列表。我们使用上面显示的Wikipedia URL进行第一次抓取。
  • 一个 parse()方法,即使目前没有操作,该方法也用于处理提取的网页我们想要的。
  • import scrapyclass spider1(scrapy.Spider):    name = 'Wikipedia'    start_urls = ['https://en.wikipedia.org/wiki/Battery_(electricity)']    def parse(self, response):        pass

    我们现在可以运行此蜘蛛以确保一切正常。它的运行方式如下。

    scrapy runspider spider1.py# prints2017-11-23 09:09:21 [scrapy.utils.log] INFO: Scrapy 1.4.0 started (bot: scrapybot)2017-11-23 09:09:21 [scrapy.utils.log] INFO: Overridden settings: {'SPIDER_LOADER_WARN_ONLY': True}2017-11-23 09:09:21 [scrapy.middleware] INFO: Enabled extensions:['scrapy.extensions.memusage.MemoryUsage', 'scrapy.extensions.logstats.LogStats',...

    关闭日志记录

    如您所见,使用最小类运行scrapy会产生一堆输出,这对我们来说没有太大意义。让我们将日志记录级别设置为 warning 并重试。将以下行添加到文件的开头。

    import logginglogging.getLogger('scrapy').setLevel(logging.WARNING)

    重新运行蜘蛛程序后,我们应该会看到最少的日志消息。

    使用Chrome检查器

    从网页中提取信息包括确定我们要从中获取信息的HTML元素的位置。在Chrome Web浏览器中查找元素位置的一种简便方法是使用检查器。

  • 在Chrome中导航到正确的页面。
  • 将鼠标放在
  • 右键单击以弹出上下文菜单。
  • 从菜单中选择检查
  • 这会弹出开发者控制台,并选择 Elements 标签。在标签下方,您应该看到状态栏,其中元素的位置如下所示:

    html body div#content.mw-body h1#firstHeading.firstHeading

    如下所述,您需要该职位的部分或全部。

    提取标题

    现在让我们向添加一些代码parse()方法以提取页面标题。

    ...    def parse(self, response):        print response.css('h1#firstHeading::text').extract()...

    该方法的 response 参数支持一种称为 css(),它将使用给定位置从页面中选择元素。对于我们的情况,该元素为 h1.firstHeading 。我们需要元素的文本内容,因此将 :: text 添加到选择中。最后, extract()方法返回选定的元素。

    在该类上再次运行scrapy时,我们得到以下输出:

    [u'Battery (electricity)']

    This显示标题已提取到Unicode字符串列表中。

    说明如何?

    为演示从网页提取数据的更多方面,让我们获得第一段

    在使用Chrome开发者控制台进行检查时,我们发现元素的位置为(右尖括号(>)表示元素之间的父子关系) ):

    div#mw-content-text> div> p

    此位置返回全部 p 元素匹配,其中包括整个描述。由于只需要第一个 p 元素,因此我们使用以下提取器:

    response.css('div#mw-content-text>div>p')[0]

    要仅提取文本内容,我们添加CSS提取器 :: text

    response.css('div#mw-content-text>div>p')[0].css('::text')

    最后一个表达式使用 extract()返回一个unicode字符串列表。我们使用python join()函数加入列表。

        def parse(self, response):        print ''.join(response.css('div#mw-content-text>div>p')[0].css('::text').extract())

    我们正在寻找使用此类运行scrapy的输出:

    An electric battery is a device consisting of one or more electrochemical cells with external connections provided to power electrical devices such as flashlights, smartphones, and electric cars.[1] When a battery is supplying electric power, its positive terminal is...

    收集数据上面的代码将提取的数据打印到控制台。当需要以JSON格式收集数据时,可以使用 yield 语句。 yield 的工作方式如下-执行包含 yield 语句的函数会将调用方称为生成器。生成器是调用者可以重复执行直到终止的函数。

    这里的代码类似于上面的代码,但是使用 yield 语句返回 p 元素。

    ...    def parse(self, response):        for e in response.css('div#mw-content-text>div>p'):            yield { 'para' : ''.join(e.css('::text').extract()).strip() }...

    您现在可以通过指定输出JSON文件来运行Spider,如下所示:

    scrapy runspider spider3.py -o joe.json

    生成的输出如下:<

    [{"para": "An electric battery is a device consisting of one or more electrochemical cells with external connections provided to power electrical devices such as flashlights, smartphones, and electric cars.[1] When a battery is supplying electric power, its positive terminal is the cathode and its negative terminal is the anode.[2] The terminal marked negative is the source of electrons that when connected to an external circuit will flow and deliver energy to an external device. When a battery is connected to an external circuit, electrolytes are able to move as ions within, allowing the chemical reactions to be completed at the separate terminals and so deliver energy to the external circuit. It is the movement of those ions within the battery which allows current to flow out of the battery to perform work.[3] Historically the term \"battery\" specifically referred to a device composed of multiple cells, however the usage has evolved additionally to include devices composed of a single cell.[4]"},{"para": "Primary (single-use or \"disposable\") batteries are used once and discarded; the electrode materials are irreversibly changed during discharge. Common examples are the alkaline battery used for flashlights and a multitude of portable electronic devices. Secondary (rechargeable) batteries can be discharged and recharged multiple...

    处理信息的多个位

    现在让我们看一下提取与信息相关的多个位。在此示例中,我们将提取当前周末的热门IMDb票房收入。可以在http://www.imdb.com/chart/boxoffice的表中找到此信息,该表中包含每个匹配项的信息行。

    我们使用以下 parse()方法。再次如上所述,使用Chrome开发者控制台确定了CSS元素的位置:

    运行蜘蛛现在会返回以下JSON:

    [{"gross": "$93.8M", "weeks": "1", "weekend": "$93.8M", "image": "https://images-na.ssl-images-amazon.com/images/M/MV5BYWVhZjZkYTItOGIwYS00NmRkLWJlYjctMWM0ZjFmMDU4ZjEzXkEyXkFqcGdeQXVyMTMxODk2OTU@._V1_UY67_CR0,0,45,67_AL_.jpg", "title": "Justice League"},{"gross": "$27.5M", "weeks": "1", "weekend": "$27.5M", "image": "https://images-na.ssl-images-amazon.com/images/M/MV5BYjFhOWY0OTgtNDkzMC00YWJkLTk1NGEtYWUxNjhmMmQ5ZjYyXkEyXkFqcGdeQXVyMjMxOTE0ODA@._V1_UX45_CR0,0,45,67_AL_.jpg", "title": "Wonder"},{"gross": "$247.3M", "weeks": "3", "weekend": "$21.7M", "image": "https://images-na.ssl-images-amazon.com/images/M/MV5BMjMyNDkzMzI1OF5BMl5BanBnXkFtZTgwODcxODg5MjI@._V1_UY67_CR0,0,45,67_AL_.jpg", "title": "Thor: Ragnarok"},...]

    使用履带

    现在,让我们以一些要点来结束本文:

  • 使用scrapy python可以轻松编写网站搜寻器以提取所需的任何信息。
  • Chrome开发者控制台(或Firefox的Firebug工具)有助于找到要提取的元素位置。
  • Python的 yield 语句有助于提取重复的数据元素。
  • 您是否有任何特定的网站抓取有哪些项目?您尝试将其付诸实施时遇到什么问题?请在下面的评论中告知我们。

    图片来源:dxinerz / Depositphotos | Lulzmango / Wikimedia Commons

    标签: 编程 Python 网站管理员工具