我们的骄傲!非遗数据采集,来自官方的数据,Python爬虫无所不爬

举报
梦想橡皮擦 发表于 2022/01/09 18:41:29 2022/01/09
【摘要】 本次要抓取的数据为《中国非物质文化遗产数字博物馆》,仅技术学习。有一说一,非遗数据网站做的非常漂亮。 目标数据源分析目标站点:http://www.ihchina.cn/,数据存在下图所示位置:原则上可以针对所有分类抓取,为降低网站访问频率,只采集单一分类,即 http://www.ihchina.cn/project#target1。页面数据为异步加载,通过点击分页获得如下数据:http:...

本次要抓取的数据为《中国非物质文化遗产数字博物馆》,仅技术学习。
有一说一,非遗数据网站做的非常漂亮。

目标数据源分析

目标站点:http://www.ihchina.cn/,数据存在下图所示位置:

原则上可以针对所有分类抓取,为降低网站访问频率,只采集单一分类,即 http://www.ihchina.cn/project#target1

页面数据为异步加载,通过点击分页获得如下数据:

http://www.ihchina.cn/Article/Index/getProject.html?province=&rx_time=&type=&cate=&keywords=&category_id=16&limit=10&p=1
http://www.ihchina.cn/Article/Index/getProject.html?province=&rx_time=&type=&cate=&keywords=&category_id=16&limit=10&p=2

其中参数分别为:

  • province:所属地区;
  • rx_time:公布时间;
  • type:类别;
  • cate:类型;
  • keywords:关键词;
  • category_id:分类 ID;
  • limit:每页数据量;
  • p:页码。

本案例整体代码应该与上一案例相似,重点要看的是本次的数据返回。下图为服务器响应数据,其中核心数据存在于 list 当中,但开发人员将分页格式进行了返回,分页 HTML 标签进行了返回,以上数据在部分项目中存在参考价值。

编码时间

本次为 threading 模块的最后一个案例,在初级爬虫阶段,掌握基本的多线程应用即可。

在实测过程中,有一个经典的采集技巧可以使用,即测试服务器单次接口最大返回数据量,在本案例中,你可以手动修改上述请求地址的 limit 参数,例如将其修改为 100,该值会返回 100 条数据。

出现上述情况,就说服务器对单次返回数据没有限制,所以原则上你是可以直接修改为 3610(目标分类所有数据)的。

这样就可以实现一次访问接口,获取全部数据(不过当返回的数据量大时,接口相应速度会变慢,建议根据实际情况调整) 。

完整代码如下所示

import threading
import requests
import random

class Common:
    def __init__(self):
        pass

    def get_headers(self):
        uas = [
            "Mozilla/5.0 (compatible; Baiduspider/2.0; +http://www.baidu.com/search/spider.html)",
            "你自己的UA值,或者可以从之前的博客中获取"
        ]
        ua = random.choice(uas)
        headers = {
            "user-agent": ua,
            "referer": "https://www.baidu.com"
        }
        return headers


def run(index, url, semaphore, headers):
    semaphore.acquire()  # 加锁
    res = requests.get(url, headers=headers, timeout=5)
    res.encoding = 'utf-8'
    text = res.text
    save(index,text)
    semaphore.release()  # 释放

# 存储的数据中文进行了 UNICODE 编码,分析的时候注意转化
def save(index, text):
    with open(f"./非遗数据/{index}.json", "w", encoding="utf-8") as f:
        f.write(f"{text}")
    print("该URL地址数据写入完毕")


if __name__ == '__main__':
    c = Common()
    url_format = 'http://www.ihchina.cn/Article/Index/getProject.html?province=&rx_time=&type=&cate=&keywords=&category_id=16&limit=10&p={}'
    # 拼接URL,全局共享变量,362 页直接设置,没有动态获取
    urls = [url_format.format(i) for i in range(1, 362)]
    # 最多允许5个线程同时运行
    semaphore = threading.BoundedSemaphore(5)
    for i, url in enumerate(urls):
        t = threading.Thread(target=run, args=(i, url, semaphore, c.get_headers()))
        t.start()
    while threading.active_count() != 1:
        pass
    else:
        print('所有线程运行完毕')
【版权声明】本文为华为云社区用户原创内容,未经允许不得转载,如需转载请自行联系原作者进行授权。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。