近期业务需求,需对某网站的新闻列表页的标题、链接以及跳转子链对新闻内容进行提取与下载。因此,采用Python 的Beautiful Soup完成业务需求,本文为学习beautifulsoup包的学习笔记。
在此之前声明本文以下用词的定义:
- 主链:新闻列表页的链接
- 子链:新闻列表页中每条新闻的链接,即新闻详情页的链接
- requests模块:一个支持HTTP服务的模块,主要用于HTTP请求
- re模块:正则表达式,不过多解释,等过两天单独整理一版python正则表达式的博文
当前最新版本为Beautiful Soup 4.4.0(中文官网链接),首先进行beautiful soup的安装,最新的包是兼容python2和python3的,安装方法:
$ pip install beautifulsoup4
在第一次安装失败,提示我pip版本低,需要更新版本:
输入更新指令,完成pip更新(注:需先cd进对应python根目录):
$ python.exe -m pip install --upgrade pip
第二次beautifulsoup安装成功:
这里出现的报错(WARNING)是连接超时的原因,不过最后还是成功的安装下来,此条报错先忽略。
然后是安装解析器
Beautiful Soup支持Python标准库中的HTML解析器,还支持一些第三方的解析器,其中一个是 lxml,官方文档推荐使用lxml。所以我们先来安装lxml解析器:
$ pip install lxml
此外,因为涉及跨页面提前新闻内容,所以也需要安装requests包:
$ pip install requests
此外,页面链接的参数部分若有固定位置变量规律,可补充安装正则包:
$ pip install re代码实现 获取目标html
这里有两个不同的方法实现,分为本地html读取与request直接请求url
本地html读取(更稳定)首先将网页保存在本地指定文件夹中
代码:
print出数据,调试器显示运行成功:
代码:
这里拓展一下,关于soup.find_all()方法:
#查找标签
soup.find_all('tag')
#查找文本
soup.find_all(text='text')
#根据id查找
soup.find_all(id='tag id')
#指定属性查找标签
soup.find_all('tag', {'id': 'tag id', 'class': 'tag class'})
#使用正则
soup.find_all(text=re.compile('text'))
soup.find_all(id=re.compile('text'))
#获取标签节点的文字
.get_text()
#获取标签节点的属性值
.get('href')
输出结果:
到这一步,我所需要的标题、时间以及子链已经提取出来。
打印结果:
from bs4 import BeautifulSoup
import re
import requests
import datetime
import time
# import pandas as pd
# import numpy as np
# import os
title = []
publishDate = []
href = []
content = []
_createTime=[]
_updateTime=[]
newsRank=[]
url = requests.get('https://www.cdal.com.cn/stdair/airline/eu/announcement/announcementList?sign=true').text
soup = BeautifulSoup(url, 'lxml')
#获取标题title
for i in soup.find_all('span',{'class':'li-new'}):
title.append(i.get_text())
#添加固定键
# title = list(map(lambda x: {'title': x}, title))
#获取发布日期,带正则替换,publishDate
for i in soup.find_all('span',{'class':'li-date'}):
publishDate.append(re.compile(r".").sub('/',i.get_text()))
#添加固定键
# date = list(map(lambda x: {'publishDate': x}, date))
#_createTime、_updateTime和newsRank的Unix时间戳
for i in publishDate:
s = i.lstrip('(').rstrip(')')
d = datetime.datetime.strptime(s, "%Y/%m/%d")
_createTime.append(time.mktime(d.timetuple()))
_updateTime=_createTime
newsRank=_createTime
#获取子链
for i in soup.find_all('a',href=re.compile("announcement")):
href.append('https://www.cdal.com.cn' + i.get('href'))
# # # 获取子链的内容
for i in href:
# childSoup = BeautifulSoup(requests.get(i).text,'lxml')
content.append(BeautifulSoup(requests.get(i).text,'lxml').find('div',{'class':'new-detail'}))
# #
# content = re.compile(r'p class="indent"').sub('p style="text-align:start;text-indent:2em;" class="indent"', str(content))
# content = re.compile(r'||').sub('', str(content))
# dict={'title':title,'publishDate':publishDate,'_createTime':_createTime,'_updateTime':_updateTime,'newsRank':newsRank}
# dict= {'content':content}
# df = pd.DataFrame(dict)
# df.to_csv('content1.csv')
print(content)
注释掉的部分是用于进行csv表格输出的使用及相关正则替换。



