本博客带大家一起写一个网络爬虫,主要是爬取一个新闻网站的新闻列表,在项目正式开始之前,需要补充两个知识点,分别是如何通过Python访问网络和如果通过Python解析JSON
1、前提知识点:
1.1、Python如何访问网络
Python公告urllib来访问网络
import urllib.request #导入模块
url = "https://www.baidu.com" #设置url地址
param = {} #设置参数,参数是字典
param = urllib.parse.urlencode(param).encode('utf_8') #将参数以utf-8编码方式来编码
req = urllib.request.Request(url, param)
#设置header的User-Agent属性,模拟该请求是由狐火浏览器发送的,也就是说欺骗服务器是人为发送的并未程序发送的
req.add_header("User-Agent", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:53.0) Gecko/20100101 Firefox/53.0")
response = urllib.request.urlopen(req) #访问网络
html = response.read() #读取响应的结果
result = html.decode("utf-8") #按照utf-8编码来进行解码
print(result) #输出
运行结果:
1.2、如何解析JSON
import json #导入模块
temp = "{\"name\":\"张三\", \"age\":18}" #定义一个JSON
target = json.loads(temp) #解析JSON
print(type(target)) #获取解析后的类型
print(target)
运行结果:
2、爬虫项目开始
如图,爬虫要爬取数据的网站是一个用HTML5制作的手机网站
2.1、需求说明
如上图,通过网络爬虫爬取网站的新闻列表数据,并且将新闻的标题输出在控制台
2.2、需求分解
1、通过Python访问网址获取网站响应的数据
2、判断网站响应的数据,本网站的数据传输方式是JSON
3、通过Python解析JSON,将解析好的数据输出到控制台
2.3、实现步骤(本博文使用的是Mac版的火狐浏览器,其实大部分的浏览器都是大同小异的)
- 1、使用火狐浏览器访问网站地址:http://121.42.8.95:8090/EasyApp/HuiEdu/html/index_m.html
- 2、在网页上单击右键,选择“检查元素”,如下图
- 3、点击NetWork(网络)找到请求状态为200的链接,查看Response(响应)是否是我们要爬取的数据,如下图
- 4、点击Header可以获取该链接的详细地址,点击Params可以获取访问该链接所需要传递的参数,如下图
- 5、到此,我们所需要的所有前期数据就都准备OK了,接下来按照上面的需求分解进行详细的代码实现
2.4、实现
import urllib.request #导入网络请求模块
import json #导入JSON解析模块
url = "http://121.42.8.95:8090/EasyApp/app/mobile/article/list.action" #浏览器获取的链接地址
data = {} #浏览器获取的访问该地址需要传递的参数
data['cid'] = "huihai.xuexifangfa"
data['start'] = "0"
data['size'] = "15"
data = urllib.parse.urlencode(data).encode('utf_8') #以utf8的编码格式进行编码参数
response = urllib.request.urlopen(url, data) #访问网络
html = response.read().decode("utf-8") #将响应的数据按照utf8的编码格式进行解码
# print(html) #通过控制台输出,发现响应的结果是JSON格式
target = json.loads(html) #解析JSON
print(type(target)) #查看JSON解析后的数据类型是数组,也就是新闻列表
print(type(target[0])) #查看数组第一个元素发现是字典,也就是每一条新闻
for arr in target: #循环获取每一条新闻
print(arr['title']) #控制台输出新闻的标题
运行结果:
3、丰满需求
3.1、需求说明
以上的实现虽然已经满足了我们的需求,但是往往并不是客户想要的,如果可以让用户输入栏目名称,爬取栏目下对应的文章,似乎更加的友好
3.2、需求分解
- 1、爬取所有栏目的数据
- 2、将爬取的栏目数据封装到字典当中,用户输入字典的key即可获取栏目下的文章列表
- 3、获取文章列表的方式在上一个需求中已经实现了
3.3、需求实现
import urllib.request #导入网络请求模块
import json #导入JSON解析模块
#爬取新闻列表的函数
def getArticles(cid): #将爬取新闻列表的代码封装成一个函数
url = "http://121.42.8.95:8090/EasyApp/app/mobile/article/list.action" #浏览器获取的链接地址
data = {} #浏览器获取的访问该地址需要传递的参数
data['cid'] = cid
data['start'] = "0"
data['size'] = "15"
data = urllib.parse.urlencode(data).encode('utf_8') #以utf8的编码格式进行编码参数
response = urllib.request.urlopen(url, data) #访问网络
html = response.read().decode("utf-8") #将响应的数据按照utf8的编码格式进行解码
# print(html) #通过控制台输出,发现响应的结果是JSON格式
target = json.loads(html) #解析JSON
print(type(target)) #查看JSON解析后的数据类型是数组,也就是新闻列表
print(type(target[0])) #查看数组第一个元素发现是字典,也就是每一条新闻
for arr in target: #循环获取每一条新闻
print(arr['title']) #控制台输出新闻的标题
#爬取新闻栏目列表的函数
def getChannels():
url = "http://121.42.8.95:8090/EasyApp/app/mobile/channel/list.action" #浏览器获取的链接地址
response = urllib.request.urlopen(url) #访问网络
html = response.read().decode("utf-8") #将响应的数据按照utf8的编码格式进行解码
# print(html) #通过控制台输出,发现响应的结果是JSON格式
target = json.loads(html) #解析JSON
print(type(target)) #查看JSON解析后的数据类型是数组,也就是栏目列表
dic = {} #定义一个用来映射栏目的字典
for i in range(0, len(target), 1): #通过一个for循环将所有栏目映射到字典中
dic[i] = target[i]
return dic #返回栏目字典
channels = getChannels()
print("爬取的栏目如下:")
for i in range(0, len(channels), 1): #输出所有的栏目
print("%s=%s" %(i, channels[i]['name']))
x = int(input("请输入要栏目来查询栏目下的文章\n"))
getArticles(channels[x]['id']) #通过栏目ID爬取文章列表
运行结果: