31 2 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
的。
31 2
| for each in soup.find_all('tbody'): title = each.find('a',class_ = 'topic').get_text(strip=True)
|
果然面向过程到面向对象的思维转化是个艰难的过程。
从右向左执行
url_dict[input('输入站点代号:')]=input('请输入站点url:')
,会先让你输入url,再输入站点代号。反正我觉得没差,就没动它了。