[爬虫]用Python抓取非小号网站数字货币(一)

版权声明:本文为博主原创文章,如需转载,请附带本文链接。 https://blog.csdn.net/Kandy_Ye/article/details/78807315

一、环境

  • OS:win10
  • python:3.6
  • scrapy:1.3.2
  • pymongo:3.2
  • pycharm

环境搭建,自行百度

二、本节内容说明

本节主要抓取非小号收录的所有数字货币的详情链接和数字货币名称。

三、数据库说明

1. 货币详情页链接

非小号大概收录了1536种数字货币的信息:

http://www.feixiaohao.com

这里写图片描述

为了后面抓取详细的信息做准备,需要先抓取详情页的地址,所以我们对于数字货币的链接地址数据库设计,只需要货币名称和对应的URL即可,然后是id。如下:

    name  #分类名称
    url  #分类url
    _id  #分类id

四、抓取说明

由于非小号网站在首页提供了显示全部数字货币的功能,所以我们没有必要分页抓取,偷个懒:

这里写图片描述

后面的抓取直接使用显示全部数字货币的链接:

http://www.feixiaohao.com/all/

1. 新建项目

在你的工作目录里面新建一个scrapy的项目,使用如下命令:

scrapy startproject coins

目录结构如下:

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

2. 设置使用mongodb存储数据

在setting文件里面添加如下信息:

ITEM_PIPELINES = {
    "CoinSpider.pipelines.MongoDBPipeline": 403,
}

3. MongoDBPipeline定义

在pipelines.py文件里面添加如下类:

class MongoDBPipeline(object):
    def __init__(self):
        clinet = pymongo.MongoClient("localhost", 27017)
        db = clinet["Coins"]
        self.CoinUrl = db["CoinUrl"]

    def process_item(self, item, spider):
        """ 判断item的类型,并作相应的处理,再入数据库 """
        if isinstance(item, CoinUrl):
            try:
                count = self.CoinUrl.find({'name': item['name']}).count()
                if count > 0:
                    self.CoinUrl.update({'name': item['name']}, dict(item))
                else:
                    self.CoinUrl.insert(dict(item))
            except Exception as e:
                print(e)
                pass

为了防止数据重复写入,所以在写入数据之前要判断数据库里面是否已经存储了对应的信息,如果已经存储了,那么更新对应的信息,如果没有存储,直接插入。

4. 建立数据库

在items.py文件里面新建一个Document的类,和我们之前设计的数据库保持一致,相关代码如下:

import scrapy


class CoinUrl(scrapy.Item):
    _id = scrapy.Field()
    url = scrapy.Field()
    name = scrapy.Field()

5. 创建爬虫文件

在spiders目录下面新建一个python文件,命令为CoinSpider.py,作为我们的爬虫文件,在文件里面新建一个CoinSpider的类,继承自Spider。并且需要定义以下三个属性:

  • name:
    用于区别Spider。 该名字必须是唯一的,您不可以为不同的Spider设定相同的名字。
  • start_urls:
    包含了Spider在启动时进行爬取的url列表。 因此,第一个被获取到的页面将是其中之一。
  • start_requests() 是spider的一个方法,爬虫运行的时候被调用。

相关代码如下:

import re
import json
import time
import requests
import logging
from scrapy import Spider, Selector
from scrapy.http import Request
from CoinSpider.items import *


class CoinSpider(Spider):
    name = 'CoinSpider'
    allowed_domains = ['feixiaohao.com']
    start_urls = [
        'http://www.feixiaohao.com/all/'
    ]
    logging.getLogger("requests").setLevel(logging.WARNING)  # 将requests的日志级别设成WARNING
    tool = Tool()

    def start_requests(self):
        for url in self.start_urls:
            yield Request(url=url, callback=self.parse_coin)

6. 页面分析

查看页面的信息,可以发现所有的数字货币的信息都在一个table里面:
这里写图片描述

而每一个数字货币的详细地址和名称都在它的第一个a标签里面:
这里写图片描述

所以我们只需要先抓取到每一个数字货币的a标签的内容就可以,通过selector的xpath进行定位:

'//div[@class="boxContain"]/table/tbody/tr/td/a'

获取到所有的a标签内容,注意抓取的结果是一个列表。

而我们需要是详细信息的地址和名称都在a标签的链接以及img子标签的alt值里面:
这里写图片描述

所以我们再通过正则表达式进行提取:

r'<a href="(.*?)" target="_blank">.*? alt="(.*?)">'

由于是多行提取,所以在代码里面需要加上re.S项,详见后面的代码。

从页面元素可以知道,每个数字货币的Item下面除了有一个我们需要是a之外,还有很多其他的信息也是放到a标签里面:
这里写图片描述

而这些a标签显然是不符合我们上面提取信息的正则表达式的,所以通过上面的正则表达式,获取到的信息为空,我们只需要过滤这部分信息即可。

详细代码如下:

selector = Selector(response)
items = selector.xpath('//div[@class="boxContain"]/table/tbody/tr/td/a').extract()
for item in items:
    urls = re.findall(r'<a href="(.*?)" target="_blank">.*? alt="(.*?)">', item, re.S)
    if len(urls) > 0:
         print(urls[0][0])
         print(urls[0][1])

7. 抓取过程

这里写图片描述

基本代码已经在文中贴出,写的比较乱,欢迎大家一起讨论。

部分数据截图:
这里写图片描述

没有更多推荐了,返回首页