简单爬取github下载链接

时间:2024-04-07 14:56:40

这几天在看《python3 网络爬虫实战》,里面用到了tesseract和它对应的语言包,为了避免使用这个库出错,我就开始在github上下载对应的语言包,但是无论是使用浏览器,还是wget下载,都会在下载一大半的时候出错,于是萌生了一个分开下载的念头。转念一想,自己手动根据链接下载比较简单,但是麻烦,而且重复;而恰好正在学习爬虫的相关知识,因此有了下面的代码。

本示例代码爬取了https://github.com/tesseract-ocr/tessdata这个网址的所有有效下载链接,之后下载所有链接,并放置在当前目录下的save文件夹下。

示例代码采用python3,用到的主要是requests和pyquery;前者负责获取源码,后者则是用来css解析。

下图是我的成果:

简单爬取github下载链接

简单爬取github下载链接

总共1000多M,因为实验室的网络一如既往地稳定地差,所以总是下载失败。

首先大致说一下导入的模块:

import requests
from pyquery import PyQuery as pq
from urllib.parse import urljoin
from multiprocessing.pool import Pool
import os

1.requests 负责模拟浏览器发送请求,并获得响应,然后从响应中获得html文本。

2.pyquery 负责解析html文本,获取有用的标签中的文本或属性。

3.urllib.parse 仅仅用到了urljoin这个函数,负责给链接添加协议或者是域名。

4.os 负责创建save文件夹,以及把下载的文件保存到save文件夹下。

5.multiprocessing 多线程。

base_url = 'https://github.com'

def get_items_from_url(url):
    ''' 
    从url中获取html文本,解析后返回dict
    @param url 要解析的链接
    @return dict {'name' : '文件名', 'url' : '下载链接'}
    '''
    headers = { 
        'Host' : 'github.com',
        'User-Agent' : 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.67 Safari/537.36',
    }   
    response = requests.get(url = url, headers = headers)
        
    #响应失败,则直接返回
    if response.status_code != 200:
        print('网页加载错误')
        return
    #开始解析标签
    doc = pq(response.text)
    items = doc.find('tr.js-navigation-item').items()

    for item in items:
        a = item.find('.content span a')
        name = a.text()
            
        #排除不必要的链接
        if name.find('traineddata') == -1: 
            continue
        yield {
            'name' : name,
            'url' : urljoin(base_url, a.attr('href').replace('blob', 'raw'))
        }

get_items_from_url()用来解析链接对应的html文本,获取有用的信息,在本示例下为文件名称和对应的下载链接。

注意requests.get()中添加了一个请求头,这个一般是用来模拟浏览器的;获取响应后判断了状态码即status_code是否为200(成功),不成功则直接退出;最后urljoin()函数则是给一些不存在协议或域名的链接加上缺失的部分。

def download_file(dic):
    ''' 
    下载文件
    @param dic {'name' : '文件名', 'url' : '链接'}
    '''
    name = dic['name']
    url = dic['url']
    
    #保证save文件夹存在
    if not os.path.exists('save'):
        os.path.mkdir('save')

    print('Ready download %s' % name)
    #开始下载
    try:
        response = requests.get(url)
        file_path = 'save/{0}'.format(name)

        if not os.path.exists(file_path):
            with open(file_path, 'wb') as f:
                f.write(response.content)
            print('Successfully download %s' % name)
        else:
            print('%s already downloaded' % name)
    except requests.ConnectionError:
        print('Failed download %s' % name)

在download_file()函数中,通过调用requests.get()来下载文件。

另外注意这里用的是response.content而不是response.text   注:text获取的是字符串,而content则是字节流

最后则是对上面两个函数的调用了。

if __name__ == '__main__':
    #要下载的链接
    url = 'https://github.com/tesseract-ocr/tessdata'
    #解析完成的项列表
    groups = []
    
    for item in get_items_from_url(url):
        groups.append(item)
    print('parse data success!!!')
        
    #多线程下载
    pool = Pool()
    pool.map(download_file, groups)
    pool.close()
    pool.join()

这部分则比较简单,先通过get_items_from_url()获取所有的链接,然后多线程下载文件。当下载完成后,程序结束。