Busby 的小窝

Always Try My Best!

Centos 7 安装Python 3.7 的记录

虽然Python 2.x 即将结束支持,但是在很多地方仍然默认使用Python 2.x,比如Centos 7。本文介绍手动编译Python 3.7.3 和pip 3。

Python 3.7 及pip3 安装

  1. 准备工作

    mkdir /usr/local/python3   # 创建安装目录
    wget https://www.python.org/ftp/python/3.7.3/Python-3.7.3.tgz   # 下载源文件
    tar -xzvf Python-3.7.3.tgz   # 解压
    cd Python-3.7.3   # 进入安装目录
  2. 编译安装

    sudo ./configure --prefix=/usr/local/python3   # 安装在指定目录
    sudo make
    sudo make install

    至于编译速度,按照服务器的性能,有所快慢。得益于阿里云学生机的性能,我写了这半份安装记录。

  3. 关于pip 的安装

    参考CentOS 7 安装Python3、pip3这篇教程,该教程安装的版本是3.6.0,指出仍然需要手动安装pip。但是我在安装Python 3.7.3 时发现,系统自动安装了pip3 19.0.3,如下图,应该是不需要再手动安装了。

    但是高兴地太早,由于之前在Python2 中安装过pip,直接输入pip调用的还是Python 2的,因此需要创建软链接。

配置系统环境

  1. 使用软链接,两个版本共存

    sudo ln -s /usr/local/python3/bin/python3 /usr/bin/python3

    可利用python命令使用Python 2, python3来使用Python 3。

  2. 绑定pip3 至系统,并升级版本

    sudo ln -s /usr/local/python3/bin/pip3 /usr/bin/pip3
    pip3 install --upgrade pip

    然后就可以愉快地玩耍啦~

本文主要参考EhlxrCentOS 7 安装Python3、pip3,最后更新于2019-06-10。

解决PDF文件复制后多余空行,并实现自动翻译

最前

作为一名英语并不好的小白,近期苦于阅读英文文献,常常要用到机器翻译。然而,从PDF文件中复制内容,往往会出现多余的换行情况,强迫症患者表示这很难受,如下图所示:
Error

并且这样多余的换行出现一定程度上影响了翻译的结果,也不利于中文阅读,影响看论文的速度,

解决方案

1. 利用Python将多余的换行去除掉

该功能参考了CSDN作者YLPGG的思路,使用时仅需复制需要翻译的内容到程序中,可复制多段文字,然后在内容后输入一个#(井字符号),再回车即可,代码如下:

def get_content():
    '''
    处理PDF文件复制后多余的换行
    '''
    print('请输入要翻译的内容:')
    transText = ""
    line = sys.stdin.readline()

    while line != "#\n":
            transText += line
            line = sys.stdin.readline()

    transText = transText.replace(".\n","段落")
    transText = transText.replace("\n"," ")
    transText = transText.replace("段落","\n")

    pattern = re.compile(r'\n[A-Z]')
    res = pattern.findall(transText)

    for i in res:
        transText = transText.replace(str(i),'\n'+str(i)[1])

    transText = transText.split('\n')

    for each in transText:
        get_translation(each)

2. 利用Python访问API获取翻译结果,代码如下:

2.1 百度翻译API

使用前需在百度翻译开放平台注册开发者账号,每个月有200w字符的免费翻译额度,超出后按照49元/百万字符支付当月全部翻译字符数费用,应该个人使用200w字符是够用的,论文狂魔除外。

def get_translation(q):
    '''
    调用百度翻译Api实现翻译
    '''
    appid = '百度翻译appid'
    secretKey = '百度翻译secreKey'

    url = 'https://fanyi-api.baidu.com/api/trans/vip/translate'

    try:
        compile_trans = re.compile(r'(^[\u4e00-\u9fa5]{0,}$)')
        if compile_trans.match(q):
            from_ = 'zh'
            to_ = 'en'
        else:
            from_ = 'en'
            to_ = 'zh'
        salt = random.randint(32768, 65536)

        sign = (appid + q + str(salt) + secretKey).encode("utf-8")
        m1 = hashlib.md5(sign)
        sign = m1.hexdigest()

        data = {
            'q' : q,
            'from' : from_,
            'to' : to_,
            'appid' : appid,
            'salt' : salt,
            'sign' : sign,}

        res = requests.post(url, data).text
        target = json.loads(res)
        print(target['trans_result'][0]['dst']+'\n\n\n')
    except:
        pass

其它翻译API待更新

最后

已知Bug

  1. 由于识别段落换行和多余换行区别的局限性,如果正巧某行文字的最后一个字符为“.”(英文句号),则会被认为是正常的段落换行,导致分段错误,但不影响句子的完整性。

  2. 部分英语文献中可能含有特殊字符,会导致翻译API返回错误,在程序中会被直接跳过,但大部分正常文献都没有问题。

下载链接

我的GitHub:https://github.com/busbyjrj/translate

最近更新时间:2018年8月12日

Anaconda中Spyder闪退的解决方法[2018.8.3]

最前

8月,暑假正式开始,开始重新拾起Python的学习。近期在爬取某知名论坛的时候,Anaconda中的Spyder发生意外闪退,后无法正常打开。

症状

  1. Spyder无法正常打开,进入界面后无响应,并闪退。
  2. 尝试重装Spyder,在Prompt中运行conda uninstall Spyderconda install Spyder后出现如下报错,忘记截图了,凑合着看。
    Error

网络解决方案

经过搜索,发现主要有以下几种解决方案:

  1. 方案一【未测试】

在Anaconda2\Lib\site-packages 目录下添加一个名为 sitecustomize.py 的文件,文件内容:

#file name: sitecustomize.py
import sys
sys.setdefaultencoding('utf-8')
  1. 方案二【尝试无效】

找到C:\用户\Administrator.spyder目录,删除.spyder文件夹就好了,然后启动Spyder。

  1. 方案三【尝试无效】
    重装Spyder,命令如下:

    conda uninstall Spyder
    conda install Spyder
  2. 方案四【尝试无效】
    重装整个Anaconda,但可能未将残留文件夹删除干净,经过重装后,仍然无法打开Spyder。

参考链接:https://blog.csdn.net/u011361880/article/details/76572973

最终解决方案

多次重装无果,已经准备重装系统了,突发奇想,在Navigator中新建了一个env,然后发现Spyder需要重装,于是在可视化界面里install Spyder,稍等之后发现Spyder成功安装,并能够打开,问题解决!

后又将原来的env中的所有库进行了升级,也是在可视化界面内,之后再次打开原env中的Spyder,也能够正常打开。

基于此,推测可能是在之前的运行过程中,对env中的库造成了破坏,导致无法启动Spyder。

还好这次的突发奇想,不然又要重装系统了emmmmmmm。

最近更新时间:2018年08月3日

Python 多进程爬虫初体验[2018.04.14]

最前

近期根据助教的推荐,在莫烦Python上学习了Python爬虫的新操作,主要是多进程和多线程。本次结合课程作业,体验了一把多进程的速度。

要求

输入一座城市的名称,获取其百度百科的基本介绍。如输入北京,访问 https://baike.baidu.com/item/北京 ,获得如下表格数据:

表格数据
将其中的数据提取出来,写入一个.txt文本,如下图所示:

文本数据

基本作业思路及代码

使用requests库访问页面,比原先使用urllib库更加方便,不再需要解决中文的问题。然后再利用beautifulsoup库进行提取,并写入文件。

# -*- coding: utf-8 -*-
"""
Created on Fri Mar 30 09:52:02 2018

@author: busby
"""
import re
import requests
import bs4

def open_url(url):
    # 使用headers解决百科反爬虫的问题
    headers = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:59.0) Gecko/20100101 Firefox/59.0'}
    res = requests.get(url, headers = headers).content.decode('utf-8')
    soup = bs4.BeautifulSoup(res, 'lxml')
    # print(soup)
    return (soup)

def get_details(soup):
    try: #分别获取整张表、keys、values和注释符号
        table = soup.find('div', class_="basic-info cmn-clearfix")
        table_dts = table.find_all('dt', class_="basicInfo-item name")
        table_dds = table.find_all('dd', class_="basicInfo-item value")
        table_zs = table.find_all('sup', class_="sup--normal")
    except:
        print("请重新输入正确的城市名!")
        main()

    i = 0
    max_i = len(table_dts) #获取循环次数
    keys = []
    values = []
    zss = []
    for each in table_zs: #将注释符号汇总为一个列表
        zss.append(each.text.strip().replace(" ", ""))
    while i < max_i:
        key = table_dts[i].text.strip().replace(" ", "") #先去除空格和换行符
        value = table_dds[i].text.strip().replace(" ", "") #同上
        for each in zss: #通过循环迭代,去除掉注释符号,如果没有则不会去除任何字符
            key = key.replace(each, "").strip()
            value = value.replace(each, "").strip()
        keys.append(key)   
        values.append(value)
        i += 1

    details = [keys, values, max_i] #组成列表,传参
    return(details)

def show_details(details):
    max_i = details[2]
    i = 0
    while i < max_i: #输出完整信息
        print(details[0][i]+":"+details[1][i])
        i += 1

    print('\n\n\n')
    i = 0

    r = re.compile('(\d+(\.\d+)?)') #表示小数或整数
    while i < max_i: #仅输出需要的城市面积和人口信息
        # print(details[0][i])
        if details[0][i] == '面\xa0\xa0\xa0\xa0积':
            area = r.search(details[1][i])[0]
            print("面积:" + str(area))
        if details[0][i] == '人\xa0\xa0\xa0\xa0口':
            pop = r.search(details[1][i])[0]
            print("人口:" + str(pop))
        i += 1

def main():
    while True:
        city_name = input("请输入城市名称(默认为上海,输入exit为退出):")
        if city_name == '':
            city_name = "上海"
        elif city_name == 'exit':
            print("已退出")
            break
        url = "https://baike.baidu.com/item/" + city_name
        # print(url)
        soup = open_url(url)
        details = get_details(soup)
        show_details(details)

if __name__ == '__main__':
    main()

尝试:获取中国所有县级以上城市的信息

1. 获取中国县级以上城市列表

经过多个来源尝试,最终从民政部官网上找到一份
2018年1月中华人民共和国县以上行政区划代码,利用爬虫进行爬取,整合省份信息,代码如下:

# -*- coding: utf-8 -*-
"""
Created on Wed Apr 11 11:53:39 2018

@author: busby
"""

import requests
import bs4

def get_res(url):
    res = requests.get(url).content.decode('utf-8')
    soup = bs4.BeautifulSoup(res, 'lxml')
    content = soup.find_all('td',class_="xl7012452") # 获取有用的列表信息
    id_ =[]
    name_ = []
    i = 0
    new_content = []
    for each in content:
        if each.text != "":
            new_content.append(each)

    while i < len(new_content):
        if i % 2 == 0:
            id_.append(new_content[i].text)
        else:
            name_.append(new_content[i].text)
        i += 1

    provinces = []
    cities = []
    i = 0
    while i < len(id_):
        if id_[i] == 0:
            cities.append(name_[i])
        elif id_[i][0:2] == id_[i-1][0:2]: # 切换不用的省份
            cities.append(name_[i])
        else:
            # print(cities)
            provinces.append(cities)
            cities = []
            cities.append(name_[i])
        i += 1
    return(provinces)

def write_list(provinces):
    # print(provinces)
    file = open("中华人民共和国县以上行政区划代码.txt", 'a', encoding = 'utf-8')
    for province in provinces:
        for city in province:
            file.write(city + "\n")
        file.write("\n")
    file.close

def main():
    url = 'http://www.mca.gov.cn/article/sj/tjbz/a/2018/201803/201803191002.html'
    provinces = get_res(url)
    write_list(provinces)

if __name__ == '__main__':
    main()

大致一共获取到了3200多座县级以上城市。

2.1 尝试简单循环获取所有县级以上城市的百科信息

第一次没有使用多进程,简单利用循环进行获取,结果花了半个小时才获取到所有城市的信息,基本没有丢失城市,代码如下:

# -*- coding: utf-8 -*-
"""
Created on Wed Apr 11 16:11:47 2018

@author: busby
"""

import time
import requests
import bs4

def open_url(url):
    # 使用headers解决百科反爬虫的问题
    headers = {
            'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299',
            'Referer': 'https://baike.baidu.com/item/%E5%8C%97%E4%BA%AC/128981?fr=aladdin&fromid=126069&fromtitle=%E5%8C%97%E4%BA%AC%E5%B8%82'
            }

    res = requests.get(url, headers = headers).content.decode('utf-8')
    soup = bs4.BeautifulSoup(res, 'lxml')
    # print(soup)
    return (soup)

def get_details(soup):
    try: #分别获取整张表、keys、values和注释符号
        table = soup.find('div', class_="basic-info cmn-clearfix")
        table_dts = table.find_all('dt', class_="basicInfo-item name")
        table_dds = table.find_all('dd', class_="basicInfo-item value")
        table_zs = table.find_all('sup', class_="sup--normal")
    except:
        print("请重新输入正确的城市名!")
        main()

    i = 0
    max_i = len(table_dts) #获取循环次数
    keys = []
    values = []
    zss = []
    for each in table_zs: #将注释符号汇总为一个列表
        zss.append(each.text.strip().replace(" ", ""))
    while i < max_i:
        key = table_dts[i].text.strip().replace(" ", "") #先去除空格和换行符
        value = table_dds[i].text.strip().replace(" ", "") #同上
        for each in zss: #通过循环迭代,去除掉注释符号,如果没有则不会去除任何字符
            key = key.replace(each, "").strip()
            value = value.replace(each, "").strip()
        keys.append(key)   
        values.append(value)
        i += 1

    details = [keys, values, max_i] #组成列表,传参
    return(details)

def save_details(details):
    max_i = details[2]
    i = 0
    file = open('中国县级以上城市信息简表.txt', 'a', encoding = 'utf-8')
    while i < max_i: #输出完整信息
        file.write(details[0][i]+":"+details[1][i]+"\n")
        # print(details[0][i]+":"+details[1][i])
        i += 1
    file.write('\n\n')
    file.close

def get_list():
    file = open("中华人民共和国县以上行政区划代码.txt", "r", encoding = "utf-8")
    all_lines = file.readlines()
    details = []
    provinces = []
    cities = []

    for line in all_lines:
        details.append(line.split())

    i = 0
    while i < len(details):
        if len(details[i]) != 0:
            cities.append(details[i])
        else:
            #print(cities)
            provinces.append(cities)
            cities = []
        i += 1
    return (provinces)

def main():
    st = time.time()
    num = 1
    city_lists = get_list()
    #print(city_lists)
    for province in city_lists:
        for city in province:
            #print(city[0])
            time.sleep(0.1)
            url = ("https://baike.baidu.com/item/" + city[0][:-1])
            print(url)
            soup = open_url(url)
            details = get_details(soup)
            save_details(details)
            print("已完成", city[0], "共", num, "座城市的信息获取")
            num += 1

        file = open('中国县级以上城市信息简表.txt', 'a', encoding = 'utf-8')
        file.write('\n\n\n\n\n\n\n\n\n\n')
        file.close
    print("用时:", time.time()-st)

if __name__ == '__main__':
    main()

2.2 尝试多进程循环获取所有县级以上城市的百科信息

由于简单循环实在太慢,结合新学的多进程技术,尝试修改了新代码,由于新手原因,折腾了很久都没成功,最后发现pool.map传入的参数本身需要的就是一个列表,才解决了问题,也是没有认真看视频教程好好记笔记的问题,代码如下:

# -*- coding: utf-8 -*-
"""
Created on Wed Apr 11 16:11:47 2018

@author: busby
"""

import time
import requests
import bs4
from multiprocessing import Pool

def get_details(soup):
    try: #分别获取整张表、keys、values和注释符号
        table = soup.find('div', class_="basic-info cmn-clearfix")
        table_dts = table.find_all('dt', class_="basicInfo-item name")
        table_dds = table.find_all('dd', class_="basicInfo-item value")
        table_zs = table.find_all('sup', class_="sup--normal")
    except:
        return(None)

    i = 0
    max_i = len(table_dts) #获取循环次数
    keys = []
    values = []
    zss = []
    for each in table_zs: #将注释符号汇总为一个列表
        zss.append(each.text.strip().replace(" ", ""))
    while i < max_i:
        key = table_dts[i].text.strip().replace(" ", "") #先去除空格和换行符
        value = table_dds[i].text.strip().replace(" ", "") #同上
        for each in zss: #通过循环迭代,去除掉注释符号,如果没有则不会去除任何字符
            key = key.replace(each, "").strip()
            value = value.replace(each, "").strip()
        keys.append(key)   
        values.append(value)
        i += 1

    details = [keys, values, max_i] #组成列表,传参
    return(details)

def open_url(url):
    # 使用headers解决百科反爬虫的问题
    #return(url)
    headers = {
            'User-Agent':'User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Edge/16.16299',
            'Referer': 'https://baike.baidu.com/item/%E5%8C%97%E4%BA%AC/128981?fr=aladdin&fromid=126069&fromtitle=%E5%8C%97%E4%BA%AC%E5%B8%82'
            }

    res = requests.get(url, headers = headers).content.decode('utf-8')
    soup = bs4.BeautifulSoup(res, 'lxml')
    # print(soup)
    details = get_details(soup)
    return (details)

def save_details(details):
    max_i = details[2]
    i = 0
    file = open('中国县级以上城市信息简表2.txt', 'a', encoding = 'utf-8')
    while i < max_i: #输出完整信息
        file.write(details[0][i]+":"+details[1][i]+"\n")
        # print(details[0][i]+":"+details[1][i])
        i += 1
    file.write('\n\n')
    file.close
    return('Success')

def get_list():
    file = open("中华人民共和国县以上行政区划代码.txt", "r", encoding = "utf-8")
    all_lines = file.readlines()
    details = []
    provinces = []
    cities = []

    for line in all_lines:
        details.append(line.split())

    i = 0
    while i < len(details):
        if len(details[i]) != 0:
            cities.append(details[i])
        else:
            #print(cities)
            provinces.append(cities)
            cities = []
        i += 1
    return (provinces)

def make_urls(name):
    # print("正在拼凑")
    name = name[0]
    url = "https://baike.baidu.com/item/" + str(name)
    return (url)

def main():
    num = 1
    st = time.time()
    provinces_name = get_list()
    pool = Pool(processes = 8)
    for province in provinces_name:
        provinces_urls = pool.map(make_urls, province)
        provinces_txt = pool.map(open_url, provinces_urls)
        for each in provinces_txt:
            try:
                result = save_details(each)
                print(result, num)
            except:
                print('failed', each)
            num += 1

    print(time.time()-st)

if __name__ == '__main__':
    main()

果然多进程没有让我失望,仅用3分钟就完成了3200多座城市的信息获取,从速度上完胜,但遗憾的是,我发现有几座城市的返回信息为None,暂未明白出错的原因,如有大佬路过,请赐教,非常感谢!

最后

  1. 我学习Python的GitHub主页:https://github.com/busbyjrj/Python-Learning

  2. 本次学习的代码(GitHub):https://github.com/busbyjrj/Python-Learning/tree/master/multiprocessing/city_list

  3. 本爬虫仅学习使用,请控制爬取的速度,以免影响其他用户正常使用百度,谢谢。

  4. 我的多进程代码还有问题,可能会丢失几座城市的信息,暂未查明原因,如有大佬路过,请赐教,非常感谢!

  5. 我的代码虽然例子中只用于城市信息,但实测对其他百度词条也可以使用,但也可能存在一个Bug需要修正,也请赐教,谢谢!

最近更新时间:2018年4月14日

树莓派利用samba和DLNA搭建家庭影院[2018.04.02]

前言

近期学习Python框架不顺,于是重新开始折腾树莓派放松一下。昨天利用Transmission搭建了一个PT下载器,那么既然我都下载到了不少4K视频,当然想看了,然而从树莓派硬盘下载到本地再看非常不方便,且在一些设备上也不支持,那么久想到了再搭建一个家庭影院系统,本次用到了samba和DLNA。

安装samba

sudo apt-get install samba samba-common-bin # 主程序

sudo apt-get install avahi-daemon # 能够使得一个局域网环境下的设备自动获取到树莓派的服务器

设置samba

  1. 打开/etc/samba/smb.conf配置文件,在最下面增加以下代码:

    [share]

    comment = Public Storage

    path = /home/pi/sda1 # 我的PT下载地址

    valid users = root # 可访问的用户,samba有独立的用户体系

    browseable = yes

    public = yes

    writable = yes

    create mask = 0777

    directory mask = 0777

  2. 由于samba有自己独立的用户体系,还需要将root用户增加到samba中

    smbpasswd -a root # 会提示设置密码,需输入两遍

    sudo /etc/init.d/samba restart # 重启软件生效

  3. 设置开机自动启动samba,修改/etc/rc.loca,增加如下内容:

    sudo /etc/init.d/samba start

测试samba

在Windows10 此计算机中增加一个网络地址 \你的树莓派ip地址\share,注意不要漏掉share,输入刚刚添加的root账号及密码后就能够访问。
添加网络地址

本段参考文献:https://shumeipai.nxez.com/2013/08/24/install-nas-on-raspberrypi.html

安装DLNA

sudo apt-get install minidlna # 安装主程序

设置DLNA

打开DLNA的配置文件/etc/minidlna.conf,在末尾添加如下内容:

media_dir=A,/home/pi/sda1 # A表示自动加载音乐文件,后面是我的PT目录

media_dir=P,/home/pi/sda1 # P表示自动加载图片文件

media_dir=V,/home/pi/sda1 # V表示自动加载视频文件

db_dir=/home/pi/sda1/dlna # 设置DLNA的目录

log_dir=/home/pi/sda1/dlna # 设置DLNA的日志

/etc/init.d/minidlna restart # 重启软件,配置生效

测试DLNA

  1. iPad上我使用NPlayer软件,选择网络,点击右上角的加号,直接选择扫面网络即可,可以发现树莓派的目录,输入树莓派自身的root账户和密码即可加载成功(注意不同于samba的root账户和密码,如果两者设置密码是一样的话...那就一样吧)

扫描网络
设置账户

  1. 查看服务器一共有多少个文件

    http://你的树莓派ip地址:8200/

查看文件数量

好啦,设置就到这里了,如果用其它软件或者电视,也参考类似方法,祝观影愉快~

本段参考文献:https://shumeipai.nxez.com/2015/07/12/raspberry-pi-install-dlna-streaming-media-server.html?variant=zh-cn

最近更新时间:2018年04月2日