第二人生 https://www.liu.group/ zh-CN 时光向左,人生向右;抬眼望去,尽是烟波浩渺,留点滴记忆于网络,是为第二人生! Wed, 14 Oct 2020 15:19:00 +0000 Wed, 14 Oct 2020 15:19:00 +0000 Python小屋练手④编程自测31-40 /archives/230/ /archives/230/ Wed, 14 Oct 2020 15:19:00 +0000 Ryle 31. 函数main接收一个正整数n,要求返回斐波那契数列中前n项的和。例如当n=4时,计算1、1、2、3四项之和为7。 ```python def main(n): if n == 1: return 1 elif n == 2: return 2 lst = [1, 1] for i in range(2,n): lst.append(lst[i-1]+lst[i-2]) return sum(lst) ``` 32. 函数main接收一个字符串s和正整数n,要求返回字符串s重复n次之后的长字符串,如果只传递s就返回重复3次得到的字符串。 ```python def main(s, n=3): return s*n ``` 33. 函数main接收一个字符串s和正整数n,其中n的大小不超过s的长度,要求返回字符串s循环左移n位之后的结果。 ```python def main(s, n): return s[n:]+s[0:n] ``` 34. 类Number用来模拟整数类型的部分操作,要求构造方法可以接收一个整数,并且支持2个Number对象的加法运算,返回一个Number对象,使用print()内置函数输出Number对象时得到Number对象内部实际的值。main函数接收2个Number对象,返回一个Number对象。 ```python class Number: def __init__(self, value): self.value = value def __add__(self, another): return Number(self.value + another.value) def __str__(self): return str(self.value) def main(x, y): return x+y ``` 35. 类Number模拟一个整数或实数类的部分操作,要求支持接收一个整数或者实数然后创建一个Number对象(如果初始值不是整数或实数,则设置内部数据成员的值为整数0),为Number实现属性value并支持返回和修改Number对象内部数据成员的值,要求内部数据成员只能为整数或实数,如果试图修改为非整数或者非实数时,保持原来的值不变。main函数接收2个整数或实数x,y为参数。 ```python class Number: def __init__(self, value): if type(value) != int and type(value) != float: self.__value = 0 else: self.__value = value def __set(self, value): if type(value) == int or type(value) == float: self.__value = value def __get(self): return self.__value value = property(__get, __set) def main(x, y): obj = Number(x) obj.value = y return (type(obj), obj.value) ``` 36. 函数main接收任意多个表示电阻值的正整数,要求计算并返回这些电阻并联时的实际电阻值,结果保留1位小数。【多个电阻并联时,实际电阻的倒数为各个电阻值倒数之和】 ```python def main(*para): return '{:.1f}'.format(1/sum([1/x for x in para])) ``` 37. 函数main接收一个正整数n,要求判断其是否为黑洞数,如果是则返回True,否则返回False【黑洞数:各位数字所能组成的最大数与最小数之差恰好等于原来的数,比如954-459=495】 ```python def main(n): lst = list(str(n)) lst.sort() iMin = int(''.join(lst)) lst.reverse() iMax = int(''.join(lst)) if iMax - iMin == n: return True else: return False ``` 38. 函数main接收一个正整数n,要求判断其是否为水仙数,如果是则返回True,否则返回False【水仙数:如果一个k为正整数n的各位数字的k次方之和恰好等于原来的数字n,那么n为水仙花数,比如153=1*1*1+5*5*5+3*3*3】 ```python def main(n): lst = list(str(n)) k = len(lst) nLst = [pow(int(x), k) for x in lst] if sum(nLst) == n: return True else: return False ``` 39. 函数main接收一个包含若干整数的列表lst,要求返回其中所有数字绝对值之和。 ```python def main(lst): return sum([abs(x) for x in lst]) ``` 40. 函数main接收一个字符串s,要求返回一个元组,其第一个元素是s使用UTF8编码之后的字符串,第二个元素是使用GBK编码之后的字符串。如果参数s不是字符串,返回‘参数必须为字符串’ ```python def main(s): try: return ( s.encode("UTF-8"), s.encode("GBK") ) except: return '参数必须为字符串' ``` ]]> 0 /archives/230/#comments /feed/archives/230/ Python小屋练手③编程自测题21-30 /archives/229/ /archives/229/ Wed, 07 Oct 2020 06:30:00 +0000 Ryle 0 /archives/229/#comments /feed/archives/229/ Python小屋练手②编程自测题11-20 /archives/227/ /archives/227/ Tue, 06 Oct 2020 04:51:00 +0000 Ryle 0 /archives/227/#comments /feed/archives/227/ Python小屋练手①编程自测题1-10 /archives/226/ /archives/226/ Tue, 06 Oct 2020 03:38:00 +0000 Ryle = avg] ``` 5. 返回元组,第一个元素为p整除q的商,第二个元素为p对q的余数 ```python def main(p, q): return (p//q, p%q) ``` 6. 返回正整数num各位数字之和 ```python def main(num): retV = num % 10 while num // 10 > 0: num = num // 10 retV += num % 10 return retV ``` 7. 返回一个新列表,包含原列表中的唯一元素,且保持原列表中首次出现的相对位置 ```python def main(lst): retList = [] for i in range(0, len(lst)): try: index = retList.index(lst[i]) continue except: retList.append(lst[i]) return retList ``` 8. 返回一个新列表,包含原列表中每个字符串变成小写之后的字符串 ```python def main(lst): return [x.lower() for x in lst] ``` 9. 返回一个新列表,将原列表中每个字符串长度从大到小排列 ```python def main(lst): return sorted(lst, key=lambda x:len(x), reverse=True) ``` 10. 接收一个正整数n,返回n的阶乘,编写代码调用改函数,分别计算并输出20,、30、40的阶乘,不允许修改已有代码 ```python from functools import reduce from operator import mul def main(n): return reduce(mul, range(1, n+1)) print(main(20)) print(main(30)) print(main(40)) ``` ]]> 0 /archives/226/#comments /feed/archives/226/ ④上代码 /archives/225/ /archives/225/ Fri, 25 Sep 2020 13:47:00 +0000 Ryle 0 /archives/225/#comments /feed/archives/225/ ③用configparser解析配置文件 /archives/224/ /archives/224/ Fri, 25 Sep 2020 13:25:00 +0000 Ryle 0 /archives/224/#comments /feed/archives/224/ ②用python的shelve包持久化存储密码 /archives/223/ /archives/223/ Fri, 25 Sep 2020 13:25:00 +0000 Ryle 0 /archives/223/#comments /feed/archives/223/ ①pywin32和pyautogui实现微信随申码自动截取并在钉钉和晓黑板上传 /archives/222/ /archives/222/ Fri, 25 Sep 2020 13:14:00 +0000 Ryle 0 /archives/222/#comments /feed/archives/222/ 爬取新浪博客文章的Python实现之② /archives/19/ /archives/19/ Tue, 01 Sep 2020 14:19:00 +0000 Ryle Blog.py ```python class Blog(object): def __init__(self, title, url, publish, comment, read, picAddress, content, tag, category): self.title = title #主题 self.url = url #URL self.publish = publish #发表日期 self.comment = comment #评论数 self.read = read #阅读数 self.picAddress = picAddress #图片地址列表,无的话为空 self.content = content #内容 self.tag = tag #标签列表,无的话为空 self.category = category #类别 def show(self): print("title: ", self.title) print("url:", self.url) print("comment", self.comment) print("read", self.read) print("picAddress", self.picAddress) print("tag", self.tag) print("category", self.category) print("content", self.content) ``` ##### getBlogofSina.py ```python import sys, urllib, urllib.request as requests, re, codecs, html from bs4 import BeautifulSoup from ConfigData import ConfigData as cd from Blog import Blog # 取得博文详细信息 def get_BlogDetail(strUrl): #retBlog = Blog(title, strUrl, publish, comment, read, picAddress, content, tag, category) request = requests.Request(strUrl) response = requests.urlopen(request) html = response.read() soup = BeautifulSoup(html, 'html.parser') # 查找包含TAG和CATEGORY的段落 strFindList = str(soup.find_all('div', cd.patternTagDiv)) tagList = re.findall(cd.patternTag, strFindList) if tagList != None and len(tagList) > 0: tag = (str(re.findall(cd.patternTag, strFindList)[0])[6:-2]).split(",") else: tag = [] categoryList = re.findall(cd.patternCategory, strFindList) if categoryList != None and len(categoryList) > 0: category = (str(re.findall(cd.patternCategory, strFindList)[0])[1:-3]).split(",") else: category = [] # 查找TITLE的段落 strFindList = str(soup.find('title')).strip() title = strFindList[7:-8].split("_")[0] # print(title) # 查找发表时间的段落 strFindList = str(soup.find_all('span', cd.patternTitleDetail)) publish = str(re.findall(cd.patternPublishDetail, strFindList)[0]) # 用Python发送API,获取JS返回值的方式获取评论数和阅读数 comment, read = get_cr_num(strUrl, get_crDict("&aids=" + strUrl[-11:-5])) # 获得博文内容 content = str(soup.find('div', cd.patternContent )) # 获得图像地址列表 strFindList = soup.find_all('img', title=re.compile(title)) picAddressList = [] for strFind in strFindList: picAddress = str(re.findall(r'real_src=.+src=', str(strFind)))[12:-6].strip()[:-1] picAddress = picAddress.replace('&', '&') picAddressList.append(picAddress) return Blog(title, strUrl, publish, comment, read, picAddressList, content, tag, category) # 取得评论和阅读数的字典合集 # INPUT: param (&aids=02vdeu,0136nk) # RETURN: r - 评论数; c - 阅读数 def get_crDict(param): url = cd.crUrl + param request = requests.Request(url) response = requests.urlopen(request) pattern = cd.patternCR htmlW = str(re.findall(pattern, str(response.read()).strip())[0][:-1]) return e v a l(htmlW) # 返回字典 把e v a l的空格都要去掉,这个编辑器没法提交,所以只能加空格 # 取得评论和阅读数 # INPUT: _url (http://blog.sina.com.cn/s/blog_5922f3300101e20o.htm) # RETURN: r - 评论数; c - 阅读数 def get_cr_num(strUrl, cr_dict): needFindKey = strUrl[-11:-5] return cr_dict[needFindKey].get('c'), cr_dict[needFindKey].get('r') def makeBlogList(): # 保存具体内容的待爬取URL清单 needProcessURL = set() # 需要爬取的URL列表 starUrlList = [] for i in range(1,5): starUrlList.append(cd.strUrl + str(i) + ".html") # 生成博客文章一览表,格式: # 序号 | 主题 | URL| 是否有图| 评论数/阅读数| 发表时间 fout = codecs.open('sina.html', 'w', encoding='utf-8') fout.write(cd.htmlStart) i=1 # 博客文章序号 blogList = [] for url in starUrlList: request = requests.Request(url, headers=cd.headers) response = requests.urlopen(request) html = response.read() soup = BeautifulSoup(html, 'html.parser') # strFindList = soup.find_all('a', href=re.compile(cd.patternALink)) strFindList = soup.find_all('div', cd.patternDiv) paramCR = '&aids=' for strFind in strFindList: strFind = str(strFind) resUrl = re.findall(cd.patternUrl, strFind)[0] blogList.append(get_BlogDetail(str(resUrl))) for blog in blogList: hasPic = cd.outPic if len(blog.picAddress) > 0 else '' fout.write(cd.htmlCont.format(str(i), blog.title, blog.url, blog.url, hasPic, blog.comment, blog.read, blog.publish)) i += 1 fout.write(cd.htmlEnd) fout.close() if __name__ == '__main__': makeBlogList() ``` ]]> 0 /archives/19/#comments /feed/archives/19/ 爬取新浪博客文章的Python实现之① /archives/18/ /archives/18/ Tue, 01 Sep 2020 13:58:00 +0000 Ryle 实现路径 1. 确定爬取内容的HTML结构,设计对应的存储结构 2. 确定爬取内容的HTML、JS、CS的结构,确定可能的技术路线 3. 首先实现爬取和数据抓取,然后后续实现和typecho的对接 ##### 要点难点 1. 正则表达式熟练度不够,又不想花费太多时间; 2. 不是所有的内容都能在HTML代码中找到的,需要用到Firefox的WEB开发工具->网络->XHD等等去确定这些必要的信息是怎么来的。再去观察Request的信息头,看看发送哪些数据,发到哪个接口 3. 自己的图片怎么样抓下来 ##### 程序实现 经过上面的考量,整个程序(爬取部分)分成3个模块: 1. 一个是设置一些常用参数的-ConfigData.py 2. 一个是设置访问对象结构的-Blog.py 3. 然后就是一个主要的动作程序-getBlogofSina.py ##### ConfigData.py ```python #ConfigData.py #一些固定的设置 import logging class ConfigData(object): # 设置初始URL # 新浪博客的URL为 articlelist_+【用户id】+ _d + _d + .html # 第一个_d: 0表示全部文章;1开始表示分类文章 # 第二个_d: 表示页码从1开始 strUrl = 'http://blog.sina.com.cn/s/articlelist_1495462704_0_' # 设置爬虫的浏览器User-Agent # https://useragent.buyaocha.com 获得当前浏览器的User-Agent headers = { 'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; \ rv:80.0) Gecko/20100101 Firefox/80.0' } # 分析新浪博客的博文目录,得到博文目录列表页的解析正则表达式 # http://blog.sina.com.cn/s/articlelist_1495462704_0_2.html patternUrlList = r'articlelist[\w]*_0_[\w]*.html' # 得到博文目录列表页中每页的博文连接的解析正则表达式 #
#

# # # 完美数和亲和数Python和C # #

#

# # 2020-08-17 22:16 # # #

#
#patternALink = r'5922f3300[\w]+.html' patternDiv = {'class': 'articleCell SG_j_linedot1'} patternUrl = r'http:\/\/[\w\.\/]*.html' patternTitle = r'>[\u4e00-\u9fa5\w]+' patternPic = r'img' patternPublish = r'\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}' outPic = '有图' # 获取博客文章详细页面的正则表达式 patternTagDiv = {'class': 'articalTag'} patternTag = r"\$tag=.+" #获取TAG patternCategory = r'\>[\u4e00-\u9a5e\w\s]+\<\/a' patternTitleDetail = {'class': 'time SG_txtc'} patternPublishDetail = r'\d{4}-\d{2}-\d{2}\s+\d{2}:\d{2}:\d{2}' patternContent = {'class': 'articalContent'} # 评论和阅读数量来自于js,通过firefox的web开发工具【网络】查看其api接口和参数 # 其初始#url='http://comet.blog.sina.com.cn/api?maintype=num&uid=5922f330&aids=02z36z,02z2zj,02x881,02vdeu,02v0dv,02uwl0,01fdfa,01e20o,01dzuf,01dqjv,01dmef,01dkrs,01db4f,01d9bi,01d5om,01d5bj,01d2wt,01d2mg,01cx8d,01cx7e,01brlp,01b1ik,01av40,01anza,01a5u8,019zlo,019uv9,019tsy,019rli,015lxq,0156di,0150o8,014z1t,014wcu,014u1r,014rjf,014ovo,014ov5,014ovm,014ov1,014ov6,014o1b,0149fb,0149f4,0137za,0137q6,0137kc,0137ea,0137d9,0136nk&requestId=aritlces_number_6610&fetch=c,r' # 发现url='http://comet.blog.sina.com.cn/api?maintype=num&fetch=c,r&uid=5922f330&aids=02z36z,02z2zj,02x881,02vdeu,02v0dv,02uwl0,01fdfa,01e20o,01dzuf,01dqjv,01dmef,01dkrs,01db4f,01d9bi,01d5om,01d5bj,01d2wt,01d2mg,01cx8d,01cx7e,01brlp,01b1ik,01av40,01anza,01a5u8,019zlo,019uv9,019tsy,019rli,015lxq,0156di,0150o8,014z1t,014wcu,014u1r,014rjf,014ovo,014ov5,014ovm,014ov1,014ov6,014o1b,0149fb,0149f4,0137za,0137q6,0137kc,0137ea,0137d9,0136nk' # 即可,也就是说必要的参数包括maintype, fetch, uid和aids # 在这里,uid = 5922f330, aids需要动态构筑,就是具体博文的后6位 # 博文: http://blog.sina.com.cn/s/blog_5922f3300101e20o.html # 其中: 5922f330为uid, 01用途不详, 后面六位 01e20o为aid # 为了后面处理方便,为保持程序灵活性,以后可将uid也设成动态构筑 crUrl = 'http://comet.blog.sina.com.cn/api?maintype=num&fetch=c,r&uid=5922f330' patternCR = r'{.*}\)' # 设置logging的格式和级别 loggingLevel = logging.DEBUG loggingFormat = '%(asctime)s - %(filename)s[line:%(lineno)d] - %(levelname)s: %(message)s' # 设置初始URL startURL = 'http://blog.sina.com.cn/s/articlelist_1495462704_0_1.html' # 设置输出格式 htmlStart = ''' 新浪博客抓取结果
我的新浪博客  :   烟波满目凭栏久 (http://blog.sina.com.cn/liusanrong)
''' htmlCont = ''' ''' htmlEnd = '
序号 主题 URL 是否有图 评论数/阅读数 发表时间
{} {} {} {} {}/{} {}

' if __name__ == '__main__': pass ``` ]]>
0 /archives/18/#comments /feed/archives/18/