维基百科离线数据python爬取

通过爬取https://dumps.wikimedia.org/other/enterprise_html/runs/20230201/上的文件,把维基百科的数据给爬了下来做数据分析用。
维基百科提供了一个离线版的数据下载,每周更新,该数据集包含了各个国家的维基百科数据。
下载的难点是数据量大每个文件的大小也特别大,中文版的维基百科数据词条有20GB,使用代码爬取的难度是在网络连接不稳定的情况如何下载这些数据集。

以下是我的实现,实现了下载检查本地是否已经存在该文件,和断点续传。

python代码实现:

# -*- coding:utf-8 -*-

import sys
import requests
import os
from urllib.request import urlopen
from bs4 import BeautifulSoup
import requests
import time

import ssl

import socket

# 屏蔽warning信息
requests.packages.urllib3.disable_warnings()


def download(url, local_dir):
    # 延迟一秒再下,防止请求过密集导致ip被ban
    time.sleep(1)

    # 第一次请求是为了得到文件总大小
    r1 = requests.get(url, stream=True, verify=False)

    content_disposition = r1.headers.get("Content-Disposition")

    # 获取文件名称
    if content_disposition:
        file_name = content_disposition.split("filename=")[1].strip('"')
    else:
        file_name = url.split("/")[-1]

    # 为每一个国家建立一个文件夹
    dir = file_name.split("wik")[0]
    if dir != '':
        local_dir += dir + "/"



    # 文件夹不存在则新建一个
    if not os.path.exists(local_dir):
        os.makedirs(local_dir)

    print("当前正在下载文件:", file_name)
    file_path = local_dir + file_name

    # 获取文件的总大小
    total_size = int(r1.headers['Content-Length'])
    # 先看看本地文件下载了多少
    if os.path.exists(file_path):
        temp_size = os.path.getsize(file_path)  # 本地已经下载的文件大小
    else:
        temp_size = 0

    if temp_size == total_size:
        print("该文件已经下载过了!")
    else:
        # 显示一下已经下载了多少
        print(f"续传文件大小:{temp_size},文件总大小:{total_size}")

        # 核心部分,这个是请求下载时,从本地文件已经下载过的后面下载
        headers = {'Range': 'bytes=%d-' % temp_size}
        # 重新请求网址,加入新的请求头的
        with requests.get(url, stream=True, verify=False, headers=headers) as r:
            # "ab"表示追加形式写入文件
            with open(file_path, "ab") as f:
                for chunk in r.iter_content(chunk_size=1024):
                    if chunk:
                        temp_size += len(chunk)
                        f.write(chunk)
                        f.flush()

                    ###这是下载实现进度显示####
                    done = int(50 * temp_size / total_size)
                    sys.stdout.write("    《-----------下载进度:")
                    sys.stdout.write("\r[%s%s] %d%%" % ('█' * done, ' ' * (50 - done), 100 * temp_size / total_size))
                    sys.stdout.flush()
    print()


# 下载一个页面的所有链接
def download_wiki(url, local_dir):
    error_url = []
    links = []

    html = urlopen(url)  # 获取下载列表网页
    bs = BeautifulSoup(html, 'html.parser')  # 解析网页
    hyperlink = bs.find_all('a')  # 获取所有超链接

    for h in hyperlink:
        href = h.get('href')
        href = str(href)
        if href.endswith('.gz') and href.startswith('zh') and href.find('NS0') != -1:  # 获取所有以.gz结尾的文件
            links.append(url + href)

    del links[0]  # 删除第一个

    for i, url in enumerate(links):
        try:
            download(url, local_dir)
        except Exception as e:
            error_url.append(url, e)
            print(f"下载出现错误 {str(e)}")
    return links, error_url


if __name__ == '__main__':
    links, error_url = download_wiki("https://dumps.wikimedia.org/other/enterprise_html/runs/20230201/", "D:\\23711\desktop\wiki_project\wiki_data")
    print(error_url)
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值