下面是代码,代码有注释,很容易理解。
注意:爬虫代码每过一段时间就 需要更新,因为爬的东西在变,所以可能过一段时间就要更新爬虫。
# -*- coding: utf-8 -*-
"""
Created on Wed Sep 29 14:01:28 2018
@author: ESionJL数据猫
question:1.当前url若爬取到的pagelinks为[],则将其移除visited列表。
2.spiderpage()函数中,当前url爬取到的网页为UNknown,会报错,如何规避,并将此url移除。
3.返回title为空
4.网站不可加载
5.过期网站,垃圾网站
"""
import re
import requests
from bs4 import BeautifulSoup
from urllib import request
from urllib import error
#此测试首页是否可以链接
def url_get(num_retries=5):
# url = input("请输入要爬取的首页url:")
url = "http://"
# url = "http://"
try:
# 做一个user-agent模拟浏览器发送请求,也可以加入其它字段
kv = {'User-Agent':'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:61.0) Gecko'}
requests.get(url, headers=kv)
return url
except error.URLError or error.HTTPError as e:
if num_retries > 0:
if hasattr(e,'code') and 500 <= e.code < 600:
url_get(num_retries-1)
print("url无法连接")
#此函数用于提取各链接网站下的所有链接
def spiderpage(url):
try:
kv = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; WOW64) Chrome/57.0.2987.98 Safari/537.36 LBBROWSER'}
r = requests.get(url, headers=kv)
r.encoding = r.apparent_encoding
pagetext = r.text
# 正则表达式表示要爬取的是<a href="和"中的内容,"或'都可以,即当前页面下所有的链接url,返回列表
pagelinks = re.findall(r'(?<=<a href=\").*?(?=\")|(?<=href=\').*?(?=\')', pagetext)
# print(pagelinks)
return pagelinks
except:
pagelinks = ['http://']
print("这个网站有点东西")
return pagelinks
#此函数用来检测链接是否为外网链接或者不合格链接
def getTitle(url):
# 检验是否为本站链接,防止死循环爬取,如链接跳出本站则不进行操作
headers = {'Accept': '*/*',
'Accept-Language': 'en-US,en;q=0.8',
'Cache-Control': 'max-age=0',
'User-Agent': 'Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/48.0.2564.116 Safari/537.36',
'Connection': 'keep-alive',
'Referer': 'http://www.baidu.com/'
}
print(url)
req = request.Request(url, headers=headers)
html = None
try:
response = request.urlopen(req)
html = response.read().decode('utf-8')
soup = BeautifulSoup(html, "html.parser")
if soup.body is not None:
url_list = soup.head.title
title = url_list.string
print(title)
if title != None:
return title
else:
return "这网站没有灵性"
else:
title = "不可加载"
return title
# except error.URLError or error.HTTPError or error.UnicodeDecodeError:
except:
print("这网站没有灵性")
return "不可加载"
#正则删选函数
def url_filtrate(pagelinks):
same_target_url = []
try:
for murl in pagelinks:
murl = re.sub(r'\s+','', murl)
if re.findall("^java",murl) or re.findall("^jse",murl) or re.findall("^ALL",murl) or re.findall("pdf$",murl) or re.findall("^login",murl) or re.findall("css$",murl) or re.findall("@",murl):
pagelinks.remove(murl)
elif re.findall("^http",murl) and re.findall("newchinalife",murl) is None:
pagelinks.remove(murl)
elif re.findall("^http",murl):
murl = str(murl)
same_target_url.append(murl)
elif re.findall("^java",murl) or re.findall("^jse",murl) or re.findall("^ALL",murl) or re.findall("pdf$",murl) or re.findall("^login",murl):
pagelinks.remove(murl)
elif re.findall("gsp$",murl) or re.findall("shtml$",murl) or re.findall("[0-9]*$",murl):
murl = "https://www.newchinalife.com" + str(murl)
same_target_url.append(murl)
elif re.findall("^/",murl):
murl = "https://www.newchinalife.com" + str(murl)
same_target_url.append(murl)
else:
pass
except ValueError as e:
pass
# 去除重复url
unrepect_url = []
for l in same_target_url:
if l not in unrepect_url:
unrepect_url.append(l)
print(unrepect_url)
return unrepect_url
class linkQuence:
def __init__(self):
# 已访问的url集合
self.visited = []
# 待访问的url集合
self.unvisited = []
# 获取访问过的url队列
def getvisitedurl(self):
return self.visited
# 获取未访问的url队列
def getunvisitedurl(self):
return self.unvisited
# 添加url到访问过得队列中
def addvisitedurl(self, url):
return self.visited.append(url)
# 移除访问过得url
def removevisitedurl(self, url):
return self.visited.remove(url)
# 从未访问队列中取一个url
def unvisitedurldequence(self):
try:
return self.unvisited.pop()
except:
return None
# 添加url到未访问的队列中
def addunvisitedurl(self, url):
if url != "" and url not in self.visited and url not in self.unvisited:
return self.unvisited.insert(0, url)
# 获得已访问的url数目
def getvisitedurlount(self):
return len(self.visited)
# 获得未访问的url数目
def getunvistedurlcount(self):
return len(self.unvisited)
# 判断未访问的url队列是否为空
def unvisitedurlsempty(self):
return len(self.unvisited) == 0
class Spider():
def __init__(self, url):
self.linkQuence = linkQuence() # 将队列引入本类
self.linkQuence.addunvisitedurl(url) # 传入待爬取的url,即爬虫入口
#真正的爬取链接函数
def crawler(self,urlcount):
# 子页面过多,为测试方便加入循环控制子页面数量
x = 1
while self.linkQuence.unvisited or x==urlcount:
# 若子页面不是很多,可以直接使用队列中的未访问列表非空作为循环条件
# while not self.linkQuence.unvisitedurlsempty():
if x > 1:
print(f"第{x-1}个url,开始爬")
visitedurl = self.linkQuence.unvisitedurldequence() # 从未访问列表中pop出一个url
if visitedurl is None or visitedurl == '':
continue
title = getTitle(visitedurl)
if re.findall("新华保险",title): #如果跳出本站则pass
initial_links = spiderpage(visitedurl) # 爬出该url页面中所有的链接
right_links = url_filtrate(initial_links) # 筛选出合格的链接
if not right_links:
pass
else:
self.linkQuence.addvisitedurl(visitedurl) # 将该url放到访问过的url队列中
for link in right_links: # 将筛选出的链接放到未访问队列中
self.linkQuence.addunvisitedurl(link)
x += 1
else:
pass
print(f"爬完了")
return self.linkQuence.visited
#写文件函数
def writetofile(urllist):
#写入网站并计数
x=1
for url in urllist:
# Furls.txt用于保存链接
file = open('Furls.txt', 'a', encoding='utf8')
file.write(f'{url}\n')
x += 1
file.close()
print(f'写入已完成,总计{x-1}个网页的子链接')
#主循环
if __name__ == '__main__':
url = url_get()
spider = Spider(url)
#传入要爬取的子链接数量
urllist = spider.crawler(5000)
writetofile(urllist)
1
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
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
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
还是希望大家自己学会比较好,只是粘贴毕竟学不到东西,这个主题框架不是我写的,但是真正的实现函数都是我自己一点一点写的,遇到很多困难也都解决了,能学到不少东西。