Python爬虫之动态数据的采集

Python爬虫之动态数据的采集一、简介有时候我们在用 requests 抓取页面的时候,得到的结果可能和在浏览器中看到的不一样:在浏览器中可以看到正常显示的页面数据,但是使用

大家好,欢迎来到IT知识分享网。

一、简介

有时候我们在用 requests 抓取页面的时候,得到的结果可能和在浏览器中看到的不一样:在浏览器中可以看到正常显示的页面数据,但是使用 requests 得到的结果并没有。这是因为 requests 获取的都是原始的 HTML 文档,而浏览器中的页面则是经过 JavaScript 处理数据后生成的结果,这些数据的来源有多种,可能是通过 Ajax 加载的,可能是包含在 HTML 文档中的,也可能是经过 JavaScript 和特定算法计算后生成的。

对于第一种情况,数据加载是一种异步加载方式,原始的页面最初不会包含某些数据,原始页面加载完后,会再向服务器请求某个接口获取数据,然后数据才被处理从而呈现到网页上,这其实就是发送了一个 Ajax 请求。

照 Web 发展的趋势来看,这种形式的页面越来越多。网页的原始 HTML 文档不会包含任何数据,数据都是通过 Ajax 统一加载后再呈现出来的,这样在 Web 开发上可以做到前后端分离,而且降低服务器直接渲染页面带来的压力。

所以如果遇到这样的页面,直接利用 requests 等库来抓取原始页面,是无法获取到有效数据的,这时需要分析网页后台向接口发送的 Ajax 请求,如果可以用 requests 来模拟 Ajax 请求,那么就可以成功抓取了。

1. 什么是Ajax

Ajax,全称为 Asynchronous JavaScript and XML,即异步的 JavaScript 和 XML。它不是一门编程语言,而是利用 JavaScript 在保证页面不被刷新、页面链接不改变的情况下与服务器交换数据并更新部分网页的技术。

对于传统的网页,如果想更新其内容,那么必须要刷新整个页面,但有了 Ajax,便可以在页面不被全部刷新的情况下更新其内容。在这个过程中,页面实际上是在后台与服务器进行了数据交互,获取到数据之后,再利用 JavaScript 改变网页,这样网页内容就会更新了。

2. 手写Ajax接口服务

  • 框架简介

Flask是一个基于Python并且依赖于Jinja2模板引擎和Werkzeug WSGI 服务的一个微型框架 WSGI :Web Server Gateway Interface(WEB服务网关接口),定义了使用python编写的web app与web server之间接口格式

  • 环境搭建
pip install flask
Python爬虫之动态数据的采集

3. 前端程序设计

<!DOCTYPE html><html lang="en"><head>    <meta charset="UTF-8">    <title>Title</title></head><style>    td{        width: 65px;        text-align: center;        font-size: 18px;    }</style><body><h1>hello</h1><!--style  写 CSSHTML语法  标签  table 表格--><table style="margin: 0 auto; border: 1px solid; margin-top: 100px">    <tr>        <th>序号</th>        <th>姓名</th>        <th>年龄</th>    </tr>    <tbody>        {% for i in data.data %}    <tr>        <td>{{ i.id }}</td>        <td>{{ i.name }}</td>        <td>{{ i.age }}</td>    </tr>        {% endfor %}    </tbody></table></body></html>

4.后端接口设计(Flask)

from flask import Flask,render_template,jsonify# 实例app = Flask(__name__)@app.route('/')def ff():    return render_template('feifei.html')@app.route('/xl')def susu():    data = []    for i in range(1, 10):        data.append(            {'id': i, 'name': '鱼' + str(i), 'age': 18 + i}        )    # 构造数据格式    content = {        'status': 0,        'data': data    }    return jsonify(data=content)@app.route('/api')def index():    data = []    for i in range(1,7):        data.append(            {'id':i, 'name': '鱼'+str(i), 'age':18+i}        )    # 构造数据格式    content = {        'status': 0,        'data':data    }    print(content)    # flask 框架 返回数据给前端    return render_template('index.html',data=content)if __name__ == '__main__':    app.run()

二、基本原理

初步了解了 Ajax 之后,我们再来详细了解它的基本原理。发送 Ajax 请求到网页更新的这个过程可以简单分为以下 3 步:

  • 发送请求
  • 解析内容
  • 渲染网页
Python爬虫之动态数据的采集

三、数据采集案例

1. Ajax 数据加载

Ajax 其实有其特殊的请求类型,其 Type 为 xhr,这就是一个 Ajax 请求。用鼠标点击这个请求,可以查看这个请求的详细信息。

示例网站:

https://danjuanapp.com/rank/performance http://www.cninfo.com.cn/new/commonUrl?url=disclosure/list/notice#szseGem https://cs.lianjia.com/

2. 数据采集实战

采集地址:https://cs.lianjia.com/

# encoding: utf-8 import requests from loguru import logger import json class Spdier_data(): def __init__(self): self.headers = { "Accept": "application/json, text/javascript, */*; q=0.01", "Accept-Language": "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7,zh-TW;q=0.6", "Cache-Control": "no-cache", "Connection": "keep-alive", "Pragma": "no-cache", "Referer": "https://cs.fang.lianjia.com/loupan/pg2/", "Sec-Fetch-Dest": "empty", "Sec-Fetch-Mode": "cors", "Sec-Fetch-Site": "same-origin", "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.67 Safari/537.36", "X-Requested-With": "XMLHttpRequest", "sec-ch-ua": "^\\^", "sec-ch-ua-mobile": "?0", "sec-ch-ua-platform": "^\\^Windows^^" } def http(self,url,params): res = requests.get(url,params=params,headers=self.headers) if res.status_code == 200: return res def get_data(self,url,params): response = self.http(url=url,params=params) items = response.json() lists = items.get('data').get('list') for i in lists: item = {} item['address'] = i.get('address') item['city_name'] = i.get('city_name') item['decoration'] = i.get('decoration') item['district'] = i.get('district') item['title'] = i.get('title') item['show_price_info'] = i.get('show_price_info') logger.info(json.dumps(item)) self.save_data(item) def save_data(self,data): with open('data.json','a',encoding='utf-8') as f: json.dump(data, f, ensure_ascii=False, indent=4) f.write(',') def run(self): for i in range(1,3): url = "https://cs.fang.lianjia.com/loupan/pg{}/".format(str(i)) params = { "_t": "1" } self.get_data(url,params) if __name__ == '__main__': Spdier_data().run()

四、数据去重算法

数据去重算法使用redis进行承载

redis 去重 集合类型,还有布隆算法。都是数据去重常用技术。

# encoding: utf-8

import requests
from base_request import Spiders
from lxml import etree
from loguru import logger
import time
import redis
client = redis.Redis()
import hashlib

class Crawl(Spiders):

    def __init__(self):
        self.url = 'https://36kr.com/information/web_news/latest/'
        self.maps = lambda x:x[0] if x else x

    def ma5_data(self,content):
        m = hashlib.md5()
        m.update(content.encode())
        return m.hexdigest()

    def crawl(self):
        res = self.fetch(self.url)
        html = etree.HTML(res.text)
        obj = html.xpath('//div[@class="information-flow-list"]/div')
        for i in obj:
            title = self.maps(i.xpath('.//p[@class="title-wrapper ellipsis-2"]/a/text()'))
            data_z = self.ma5_data(title) # 对数据进行压缩  减少内存损耗
            tag = client.sadd('36k',data_z) # 返回值 0 1
            if tag:
                # 表示数据可以继续爬  对数据进行入库   logger = print
                logger.info('可以入库{}'.format(title))
            else:
                time.sleep(5)
                logger.info('休息5秒钟')
                self.crawl()

    def save(self,data):
        with open('data.txt','a',encoding='utf-8') as x:
            x.write(data)
            x.write('\r\n')

    def run(self):
        while True:
            logger.info('开始启动爬虫')
            self.crawl()

if __name__ == '__main__':
    Crawl().run()

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/59916.html

(0)
上一篇 2024-06-27 16:00
下一篇 2024-06-27 18:33

相关推荐

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

关注微信