3| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 
 | import requests
 from bs4 import BeautifulSoup
 from os import _exit,path,remove,system
 from time import ctime
 
 
 cookie = 'this is cookies'
 cookies = {i.split("=")[0]:i.split("=")[-1] for i in cookie.split("; ")}
 
 headers = {'User-Agent':'this is User-Agent'
 }
 
 site_url=open('site.txt','r+',encoding='utf-8')
 
 url_read=site_url.read()
 url_dict=eval(url_read)
 
 site=list(url_dict.keys())
 
 def add_site():
 print(url_dict)
 url_dict[input('输入站点代号:')]=input('请输入站点url:')
 print(url_dict)
 site_url.seek(0)
 site_url.write(str(url_dict))
 
 while 1:
 
 print('-1.add new site')
 print('0.quit')
 for i in range(len(url_dict)):
 print(str(i+1)+'.'+site[i])
 num=int(input('请输入站点编号:'))
 if num==0:
 site_url.close()
 _exit(0)
 if num==-1:
 add_site()
 site_url.seek(0)
 url_read=site_url.read()
 site=list(url_dict.keys())
 continue
 page_num=int(input('请输入抓取页数:'))
 file_path = 'data'+'_'+site[num-1]+'.txt'
 if path.exists(file_path):
 remove(file_path)
 
 f=open(file_path, 'a', encoding='utf-8')
 f.write('抓取时间:'+ctime()+'\n')
 f.close()
 
 for page in range(page_num):
 f=open(file_path, 'a', encoding='utf-8')
 f.write('\n\n第'+str(page+1)+'页:\n')
 f.close()
 
 url = url_dict[site[num-1]]+str(page+1)
 print(url)
 response = requests.get(url, headers=headers,cookies=cookies)
 soup = BeautifulSoup(response.text, 'lxml')
 for each in soup.find_all('tbody'):
 title = each.find('a',class_ = 'topic').get_text(strip=True)
 f=open(file_path, 'a', encoding='utf-8')
 f.write('\n'.join([title]))
 f.write('\n')
 f.close()
 print('response.status_code ==',response.status_code)
 site_url.close()
 
 | 
 改进
增加了通过文件读写来更新site即站点列表;
增加了交互式查询的功能;
增加了抓取时间和抓取页面的页数(如果是用于数据分析,那这个属于是多余,但如果爬出来的结果是给人看的,那就显得很有必要了。)
注意点
文件的打开方式
只介绍我用到的两种,和试图用的一种
‘r+’:可读可写
‘a’:追加内容
‘w+’:打开即清空
前两种的差别在于文件指针初始位置:
- ‘r+’初始在文件头,read操作将其挪到文件尾,导致第二次read就读不出东西。这种时候就可以通过seek()方法更改文件指针位置,例如seek(0)就是挪到文件开头。
- ‘a’初始在文件尾,因此我们需要if path.exists(file_path): remove(file_path)来进行伪覆写。
‘w+’不是很讲理,将打开的文件视作全新文件,即使没有任何操作也会清空文件内容。
python各种对象和字符串对象的转化
其实字符串也是对象,但字符串比较偏朴素,和花里胡哨的dict、list、set什么的完全比不了。
其他对象可以使用str()转化为字符串,字符串也可以通过list()(列表)、eval(字典)等方法转化为其它类型的对象。
其他类型的强制类型转化也是类似,例如字符串可以转化为整型数,’1’可以转化为 1。
对 C 语言起手的人来说堪称魔法。
获取目前时间
使用time库的ctime()方法。
连缀
'\n'.join([title]),意思是通过换行符号将join里字符串序列连接起来。
收回前言,python字符串也挺花里胡哨的。
python中的for
看上去和 C 里的 for(i=0;i<n;i++);很像,但这里的意思是选取系列中的元素,对所有元素进行以下操作。
如果把系列,也就是soup.find_all('tbody')换成range(),那就和 C 类似了。
另外,python的for是可以使用else的。
3| 12
 
 | for each in soup.find_all('tbody'): title = each.find('a',class_ = 'topic').get_text(strip=True)
 
 | 
 果然面向过程到面向对象的思维转化是个艰难的过程。
从右向左执行
url_dict[input('输入站点代号:')]=input('请输入站点url:'),会先让你输入url,再输入站点代号。反正我觉得没差,就没动它了。