爬虫爬 JSON HTML 数据

最近这两周在忙着给公司爬一点数据,更文的速度有一点降低,预计今天就爬完了,总结总结经验。css

其实以前我司是有专门作爬虫的,不用前端这边出人干活。后来那人离职了,有可能就没有爬虫这方面的需求了。忽然又有了一些,前端这边出人作一下。老大说用 py 作,前期先调研一下。html

原理

爬虫其实原理上很简单,咱们==客户端他们==服务端
客户端发送请求 req,服务端返回响应 rsp。拿到响应以后解析数据,入库,就完事了。前端

请求数据 req

通常来讲请求分为两种,拉数据 get 比较多。
偶尔部分接口须要登陆,那就是多带 cookie 或者 headers
其实还有一部分工做就是分析入参vue

  1. get
    参数拼接在 url
  2. post
    参数放在 body

响应数据 rsp

返回数据大致上是两种python

  1. JSON
    通常来讲,经过 抓包 或者说 network 工具。咱们找到了服务端的接口,那么我直接访问这个接口便可。
    本文第一个重点来了:切换到移动端再查一遍,每每有不同的收获,通常来讲 PCM 端的进度不了,有可能都不是一个项目组,因此实现方式就会有差异。
  2. html
    比较坑的一种方式,由于没有找到 JSON 接口。无奈只能走解析 HTML 的路子。

调研

  1. Node
    以前给后台搭架子的时候使用过,主要功能点以下:mysql

    1. 自动登陆,(拿headers、cookie
    2. 存储本地,每次请求带上 token
    3. 启动代理服务
  2. py 老大说要用这个东西。咨询了一下其余朋友,说可使用下面的工具。sql

    1. requests + beautifulSoup
      使用起来其实就是 requests 发请求, beautifulSoup 解析 HTML。比较原始。
    2. scrapy
      一个爬虫的框架。我在这里学的 www.scrapyd.cn。实现上比较完整,能够设置请求间隔,随机 ua 等功能。
  3. 前端实现
    我一个铁头娃,怎么能轻言放弃?身为一个前端er,仍是这些 api 让我更加亲切数据库

    1. XHR
      发请求利器,打开对方页面,cookie 啥的都自带。无敌就是这么寂寞
      其实还能够找到对方请求发起的位置,打个断点,把对方内部的代码绑定到全局,这样一些内部逻辑什么的也都没问题。
      并且还 JSON HTML 通吃。
    2. iframe
      针对 HTML 类型的处理。同域的状况下,也无敌好吗?json

      1. HTML 获取 DOM 节点?
      2. 甚至能够取 window 上的对象。vue SSR 你感受到了威胁吗?
  4. 网上其余服务商提供的接口(真香啊)。有免费的有收费的,通常免费的限量。网页爬虫

    1. 好比抖音热度?
    2. 好比各种音乐的歌单和做品?
    3. IP 查询
    4. 天气查询

好了上面说了那么多,建议老大限制,我选择了 scrapy

scrapy

scrapy 是一个网页爬虫框架,神马叫作爬虫,若是没据说过,那就:内事不知问度娘,外事不决问谷歌,百度或谷歌一下吧!……(这里的省略号表明 scrapy 很牛逼,基本神马都能爬,包括你喜欢的苍老师……这里就不翻译了)

看到这个骚的飞起的介绍了吗?没错,我就是在上面学的。scrapy 中文站。接下来我就介绍一下我认为对于新手比较关注的东西

scrapy HTML

scrapy 处理器中的 response 标识你拿到的 rsp 上面自带了一些方法,通常来讲须要关注的只有两个

css 选择器

quote.css('span.text::text').extract_first() 中的 'span.text::text'眼熟吗?
没错,就是咱们经常使用的选择器。经过这个 api,咱们能够把咱们想要的数据,限时在一个很小的范围,而后拿字符串便可。
啥?你说你不会 css 选择器?前端培训-初级阶段(5 - 8)-CSS选择器(基本、层级、属性、伪类、伪状态)

  1. extract() 函数提取列表
  2. extract_first() 表明提取第一个元素。基本等价于 extract()[0]
  3. ::text 选择其中的文字
  4. ::attr(href) 提取属性

xpath

quote.xpath('span/small/text()').extract_first()
文档,这个我不会,我也没看

scrapy JSON

import json 使用这个类库解析如:json.loads(response.body.decode('utf-8'))

scrapy 请求方式

get

import urllib 能够用来给中文字符 encode

yield scrapy.FormRequest(
    url, 
    method = 'GET', 
    headers = self.headers, 
    formdata={}, 
    callback = self.parse_list, 
    dont_filter = True, 
    meta = {
        'offset': 0,
    })

post

数据放入 formdata 传递便可。

yield scrapy.FormRequest(
    url, 
    method = 'POST', 
    headers = self.headers, 
    formdata={}, 
    callback = self.parse_list, 
    dont_filter = True, 
    meta = {
        'offset': 0,
    })

给回调模块带参数

meta = {
        'offset': 0,
    }

以下方式接收

disstid = response.meta['offset']

外部传参方式

scrapy crawl argsSpider -a tag=爱情
内部是使用以下命令能够接收到。

def start_requests(self):
        url = 'http://lab.scrapyd.cn/'
        tag = getattr(self, 'tag', None)  # 获取tag值,也就是爬取时传过来的参数

scrapy mysql

大数据那边说爬回来的数据要入库。

  1. scrapyMysql/scrapyMysql/items.py 编写对应入库字段。

    import scrapy
    
    class ScrapymysqlItem(scrapy.Item):
        # define the fields for your item here like:
        # name = scrapy.Field()
        tag = scrapy.Field()  # 标签字段
        cont = scrapy.Field()  # 名言内容
        pass
  2. scrapyMysql/scrapyMysql/spiders/inputMysql.py 写爬虫处理操做时,入库

    item = ScrapymysqlItem()  # 实例化item类
        for v in mingyan:  # 循环获取每一条名言里面的:名言内容、做者、标签
            item['cont'] = v.css('.text::text').extract_first()  # 提取名言
            tags = v.css('.tags .tag::text').extract()  # 提取标签
            item['tag'] = ','.join(tags)  # 数组转换为字符串
            yield item  # 把取到的数据提交给pipline处理
  3. 编写MySQL存储插件:MySQLPipeline.py

    import pymysql.cursors
    class MySQLPipeline(object):
        def __init__(self):
            # 链接数据库
            self.connect = pymysql.connect(
                host='127.0.0.1',  # 数据库地址
                port=3306,  # 数据库端口
                db='scrapyMysql',  # 数据库名
                user='root',  # 数据库用户名
                passwd='root',  # 数据库密码
                charset='utf8',  # 编码方式
                use_unicode=True)
            # 经过cursor执行增删查改
            self.cursor = self.connect.cursor()
    
        def process_item(self, item, spider):
            self.cursor.execute(
                """insert into mingyan(tag, cont)
                value (%s, %s)""",  # 纯属python操做mysql知识,不熟悉请恶补
                (item['tag'],  # item里面定义的字段和表字段对应
                 item['cont'],))
            # 提交sql语句
            self.connect.commit()
            return item  # 必须实现返回
  4. settings启动MySQLPipline组件

    ITEM_PIPELINES = {
       'scrapyMysql.MySQLPipline.MySQLPipeline': 300,
    }

总结一下

到如今,咱们已经完成了全部基础知识的积累。遇到不会咱们去里看?
总结一下须要注意点的

  1. 切换 PC 和 M 端,寻找可行的方案
  2. 注意节制(部分容易限量)
  3. python 编码问题(真的好烦)
  4. 网上提供的那个 mysql 库和个人不合,我换了一个MySQLdb
  5. 第三方的接口是真香

微信公众号

clipboard.png

相关文章
相关标签/搜索