弓背霞明剑照霜,秋风走马出咸阳。这篇文章主要讲述Python 网络爬虫实战:爬取南方周末新闻文章(带关键词筛选)相关的知识,希望能为你提供帮助。
1. 分析网站南方周末,网站地址为:http://www.infzm.com/contents?term_id=1
文章图片
观察网站主页,我们可以了解到,网站左侧为 ?
?频道列表?
? ,中间为 ??新闻列表?
? 。鼠标点击切换左侧的频道时,观察到浏览器地址栏中 ?
?term_id?
? 的值同步发生变化,说明 ??term_id?
? 参数表示频道的 ??id?
? 。将网页滚动条往下滑,观察到会不断有新的新闻文章加载进来,但是浏览器地址栏中的网址全程没有变化,说明新闻列表采用 ?
?瀑布流?
? 的加载形式,数据通过 ??Ajax?
? 动态加载。简单分析之后,我们打开 ?
?开发者工具?
? ,切换到 ??Network?
? 页签开始抓包分析。1.1 新闻列表分析
文章图片
在页面下滑的过程中,不断有新的请求出现。
请求的 URL 形如: http://www.infzm.com/contents?term_id=1& page=2& format=json
【Python 网络爬虫实战(爬取南方周末新闻文章(带关键词筛选))】请求的内容如图所示:
文章图片
到这里我们知道了,这个便是我们要找的 ?
?新闻列表?
? 的数据接口。观察接口 URL:http://www.infzm.com/contents?term_id=1& page=2& format=json
有 3 个参数:?
?term_id?
? ,??page?
? 和 ??format?
? 。?
?term_id?
? 前面分析过了表示频道的 id,其他两个根据字面含义,??page?
? 表示页数,??format?
? 表示数据格式。返回的数据格式是标准的 ?
?json?
? ,文章列表数据位于 ??data ->
contents?
? ,包括文章标题,文章id,作者名字,发布时间等信息。1.2 新闻详情页分析随便打开一篇新闻文章的详情页,如:http://www.infzm.com/contents/217973 。
我们观察到详情页链接的构成方式为 ?
?http://www.infzm.com/contents/?
? + ??文章id?
? 。通过开发者工具查看,了解到新闻正文内容渲染在 ?
?html?
? 源码中。文章图片
如图所示,新闻内容在 ?
?<
div class="nfzm-content__content">
?
? 标签中。其中 ??引言?
? 部分位于 ??<
blockquote class="nfzm-bq">
?
? 标签下;正文内容位于 ??<
div class="nfzm-content__fulltext">
?
? 标签下的 ??p?
? 标签中。网页结构示意如下:
< div class="nfzm-content__content">
< blockquote class="nfzm-bq"> 引言< /blockquote>
< div class="nfzm-content__fulltext">
< p> 第一段< /p>
< p> 第二段< /p>
< p> 第三段< /p>
< /div>
< /div>
1.3 反爬机制分析我们用 python 简单编写一段代码,测试一下网站的反爬机制。
1.3.1 新闻列表
简单伪造一下 headers ,发起网络请求。
import requests
headers = {
accept: text/html,application/xhtml+xml,application/xml; q=0.9,image/webp,image/apng,*/*; q=0.8,
user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36,
}
url = "http://www.infzm.com/contents?term_id=1& page=2& format=json"
r = requests.get(url, headers=headers)
r.encoding = r.apparent_encoding
print(r.text)
发现可以正常获取到数据。
文章图片
1.3.2 新闻正文
import requests
headers = {
accept: text/html,application/xhtml+xml,application/xml; q=0.9,image/webp,image/apng,*/*; q=0.8,
user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36,
}
url = "http://www.infzm.com/contents/217973"
r = requests.get(url, headers=headers)
r.encoding = r.apparent_encoding
print(r.text)
新闻正文内容也可以成功获取到。
文章图片
不过并不是所有新闻正文都可以无障碍爬取到,有些新闻正文仅展示部分内容,全文需要登录账号之后才能查看。
文章图片
而当我注册好账号之后刷新界面,发现查看全文居然还要订阅会员。
文章图片
这里我就先不开通会员了。
如果有需要的同学,可以自行开通会员后,将登录后的 ?
?cookies?
? 填入代码中的 ??headers?
? 中,进行爬取。headers = {
accept: text/html,application/xhtml+xml,application/xml; q=0.9,image/webp,image/apng,*/*; q=0.8,
user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36,
Cookie: "你自己的cookie"
}
Cookie 可以在开发者工具中查看。
2. 编码环节接下来,开始正式编码。
首先导入这个爬虫程序需要用到的库
import requests
import json
from bs4 import BeautifulSoup
import os
然后是网络请求函数 ?
?fetchUrl?
?def fetchUrl(url):
功能:访问 url 的网页,获取网页内容并返回
参数:目标网页的 url
返回:目标网页的 html 内容
headers = {
accept: text/html,application/xhtml+xml,application/xml; q=0.9,image/webp,image/apng,*/*; q=0.8,
user-agent: Mozilla/5.0 (Windows NT 10.0; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36,
}
try:
r = requests.get(url, headers=headers)
r.raise_for_status()
r.encoding = r.apparent_encoding
return r.text
except Exception as e:
print(e)
解析新闻列表函数 ?
?parseNewsList?
?def parseNewsList(html):
功能:解析新闻列表页,提取新闻列表数据并依次返回
参数:列表数据(json 格式)
返回:新闻的id,标题,发布时间
try:
jsObj = json.loads(html)
contents = jsObj["data"]["contents"]
for cnt in contents:
pid = cnt["id"]
subject = cnt["subject"]
publish_time = cnt["publish_time"]
yield pid, subject, publish_time
except Exception as e:
print("parseNewsList error!")
print(e)
解析新闻正文内容函数 ?
?parseNewsContent?
?def parseNewsContent(html):
功能:解析新闻详情页,提取新闻正文内容并返回
参数:网页源码(html 格式)
返回:新闻正文内容的字符串
try:
bsObj = BeautifulSoup(html, "html.parser")
cntDiv = bsObj.find("div", attrs={"class": "nfzm-content__content"})
blockQuote = cntDiv.find("blockquote", attrs={"class": "nfzm-bq"})
fulltextDiv = cntDiv.find("div", attrs={"class": "nfzm-content__fulltext"})
pList = fulltextDiv.find_all("p")
ret = blockQuote.text + "\\n" if blockQuote else ""
ret += "\\n".join([p.text for p in pList if len(p.text) > 1])
return ret
except Exception as e:
print("parseNewsContent error!")
print(e)
保存文件函数 ?
?saveFile?
?def saveFile(path, filename, content):
功能:将文章内容 content 保存到本地文件中
参数:要保存的内容,路径,文件名
# 如果没有该文件夹,则自动生成
if not os.path.exists(path):
os.makedirs(path)
# 保存文件
with open(path + filename, w, encoding=utf-8) as f:
f.write(content)
爬虫调度器 ?
?download_nfzm?
?def download_nfzm(termId, page, savePath):
功能:爬取 termId 频道,第 page 页的所有新闻,并保存至 savePath 路径下
参数:termId 频道 Id
page 页码
savePath 保存路径
url = f"http://www.infzm.com/contents?term_id={termId}& page={page}& format=json"
html = fetchUrl(url)
try:
for推荐阅读
- 内网Centos7设置代理后可以上网
- 自动化运维工具ansible概述
- IFIX 需要权限打开某个画面
- Ansible之ansible.cfg
- 庖丁解牛之Android平台RTSP|RTMP播放器设计
- CentOS8.3下配置环境变量,实现执行history的时候可以看到执行命令的时间
- 当SantuCommerce插件的iframe打开时,WordPress主题损坏
- WordPress主题开发-模板引擎[关闭]
- WordPress主题开发(单击按钮时不执行javascript代码)