上一篇《人民日报》的爬虫文章发布之后,收到了很不错的反馈,文中的爬虫代码也确实帮助到了很多人,我很开心。

跟读者们交流过程中,我也发现了一些比较共性的需求,就是 根据关键词筛选 新闻文章。

最初我的想法是,在爬取到全部文章数据的基础上,遍历文件夹,然后将正文中包含关键词的文章筛选出来。

如果你已经下载到了完整的新闻数据,那用这种方法无疑是最方便快捷的。但是如果没有的话,需要先爬取全部数据,再从中筛选符合条件的数据,无疑是有点浪费时间。

本篇文章,我将介绍两种方法,一种,是从现有数据中根据关键词筛选,另一种,是利用人民网的搜索功能,爬取关键词的搜索结果。

1. 爬取关键词搜索结果

最近有读者跟我请教问题,我才发现,人民网是有搜索功能的 (http://search.people.cn)。

所以只需要根据关键词检索,然后将搜索结果爬取下来即可。

1.1 分析网页

这里我简单教一下大家分析网页的一般思路。

1.1.1 分析网页主要看什么

  • 我们能获取到哪些数据。
  • 服务器以什么形式发送数据
  • 如何获取全部数据(如何翻页)

1.1.2 如何使用浏览器的开发者工具

具体操作也很简单,按 F12 打开 开发者工具 ,切换到 Network ,然后刷新网页,可以看到列表中有很多请求。

其中有图片,js 代码, css 样式,html 源码等等等等各种各样的请求。

点击对应的请求项之后,你可以在 Preview 或者 Response 里预览该请求的数据内容,看是不是包含你需要的数据。

当然,你可以逐条去检查,也可以用顶部的过滤器去筛选请求类型(一般情况下,我们需要的数据,在 XHRDoc 里即可找到。)

找到对应的请求之后,可以切换到 headers 查看该请求的请求头信息。

如图所示,主要关注 4 个地方。

  1. Request URL:也就是请求的链接。爬虫请求的 url 填啥是要看这里,不要只知道去浏览器的地址栏里复制网址。
  2. Request Method:请求方法,有 GETPOST 两种,爬虫代码里用 requests.get() 还是 requests.post() 要与这里保持一致,否则可能无法正确获取数据。
  3. Request Headers:请求头,服务器会根据这个来判断是谁在访问网站,一般情况下,你需要设置爬虫请求头中的 User-Agent (有的网站可能需要判断 AcceptCookieRefererHost 等,根据具体情况设置),来将爬虫伪装成正常的浏览器用户,防止被反爬机制拦截。
  4. Request Payload:请求参数,服务器会根据这些参数,来确定返回哪些数据给你,比如说,页码,关键词,等等,找到这些参数的规律,就可以通过构造这些参数,来直接向服务器获取数据了。

1.1.3 服务器返回的数据有哪些形式

一般情况下,有htmljson 两种格式,接下来我简单教大家一下如何判断。

HTML 格式

一般情况下,是出现在筛选条件中的 Doc 类型里,也非常容易分辨,就是 Response 里面查看,全篇都是 </> 这种标签的。

如果确定 html 源码中包含你需要的数据的话(这么说,是因为有些情况下数据是通过 js 代码动态加载进去的,直接解析源码是找不到数据的)

可以在 Elements 中,通过左上角的箭头按钮,来方便快捷地在网页中定位数据所在的标签(具体就不细讲了,自己试一下就懂了)。

大部分人入门学习爬虫,也都是从解析 html 开始的,应该比较熟悉。解析的方法也很多,如 正则表达式BeautifulSoupxpath 等等。

Json 格式

前面也说了,有些情况下,数据并不是放在 html 页面中直接返回的,而是通过其他的数据接口,动态的请求加载进去的。这样就导致的有些同学刚开始学爬虫的时候,明明在网页上分析的时候,标签路径都没问题,但是代码请求时死活找不到标签的情况。

这种动态加载数据的机制叫 Ajax ,感兴趣的可以去自行搜索了解。

Ajax 请求一般都是在请求类型中的 XHR 中,数据内容一般以 json 格式展示。(有些同学不知道怎么判断一个请求是不是 ajax,数据是不是 json,怎么办?这里说一个简单的判断方法,在 Preview 里看它是不是类似于下图的形式,大括号,键值对 {“xxx”: “xxx”},以及可以展开合上的小三角形)

这类请求返回的数据是 json 格式,可以直接使用 python 中的 json 库来解析,非常方便。

以上给大家简单讲解了一下,如何分析网页,如何抓包的方法,希望对大家有帮助。

言归正传,通过上面介绍的方法,我们可以很容易知道,人民网搜索结果的数据是通过 Ajax 形式发送的。

请求方法是 POST,请求链接,请求头,和请求参数都可以在 Headers 里查看到。

在参数里,我们可以看到 key 应该就是我们搜索的关键词,page 是页码,sortType 是搜索结果排序方式,等等等等,知道这些规律,这样我们就可以自行构造请求了。

1.2 试探反爬机制

一般网站为了防止攻击,都会或多或少设置一些反爬机制。这里给大家简单介绍一些常见的反爬机制,以及应对办法。

1.2.1 User-Agent

服务器会根据请求头的 User-Agent 字段来判断用户是通过什么来访问的,如:

Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/88.0.4324.146 Safari/537.36

这里包含了浏览器,电脑系统的一些基本信息。如果你的 python 爬虫代码没有设置这个字段值的话,会默认是 python,这样服务器就可以大概判断出来这个请求是爬虫发起的,然后选择是否拦截。

应对办法也比较容易,就是用浏览器访问时候,把请求头里的 User-Agent 值复制下来,设置到代码里即可。

1.2.2 Referer

有些网站的资源是添加了防盗链的,也就是说,服务器处理请求的时候,是会去判断 Referer 的值的,只有在指定的站点发起请求,服务器才会允许返回数据(这样可以防止资源被盗用在其他网站使用)。

应对方法也简单,复制浏览器访问时,请求头里的 Referer 值即可。

1.2.3 Cookie

有的网站,可能有的数据需要登录账号才能访问,这里就用到了 Cookie 值。

不设置 Cookie , 设置未登录时候访问的 Cookie ,设置登录账号以后的 Cookie ,可能返回的数据结果都不一样。

应对方法因网站而异,如果不设置 Cookie 也可以访问,那就不用管;如果需要设置才能访问,那就根据情况(是否要登录,是否要会员等等)复制浏览器请求头中的 Cookie 值来设置。

1.2.4 JS 参数加密

请求的参数里,可能会有一些类似于乱码的参数,你不知道它是干什么的但是它又很重要,也不是时间戳,不填或者随便填都会请求失败。

这种情况就比较难搞了,这是 js 算法加密过的参数,要想自行构造,需要模拟整个参数加密的算法。

不过由于这个加密过程是前端完成的,所以加密算法的 js 代码是可以完全获取的到的,懂一些前端知识的,或者 Js 逆向的话,可以试着破解一下。

我个人是不建议这么做的,一是破解麻烦,二是可能会违法。

换个方法,用 selenium 或者 ``pyppeteer` 自动化去爬,它不香嘛。

1.2.5 爬取频率限制

如果长时间高频率地爬取数据的话,对网站服务器的压力是很大的,而且正常人访问也不可能做到这么高强度的访问(比如一秒访问十几次网站),一看就是爬虫干的。所以服务器一般会设置一个访问频率阈值,比如一分钟内如果发起超过 300 次请求,就视为爬虫,对其 IP 进行访问限制。

应对的话,我建议,如果不是特别赶时间的话,可以设置一个延迟函数,每爬取一次数据,随机睡眠几秒钟,使得访问频率降低到阈值以下,降低对服务器访问的压力,也减少封IP的几率。

1.2.6 其他

还有一些不太常见的,但是也比较有意思的反爬机制,给大家举几个例子。

  • 字体反爬,就是网站对一些关键数据使用了特殊的字体,只有用对应的字体文件去解析,才能正确显示,否则源码里只能看到一串乱码。
  • 反调试,就是网站通过屏蔽浏览器开发者工具,屏蔽 selenium 等常用的爬虫工具,来达到一定的反爬效果。
  • 蜜罐反爬,就是检测到你是爬虫的时候,不会直接拒绝访问,而是给你返回一些假数据。爬虫者可能爬完了才发现是假数据,而且甚至不知道是什么时候开始被替换成假数据的。

以上是常见的一些反爬机制,希望对大家有帮助。

经过测试,人民网的反爬机制并不是特别严格,参数设置对了的话,基本上爬取不会受到什么限制。

不过如果是比较大量的数据爬取时,最好设置好爬取延时 以及 断点续爬 功能。

1.3 完善代码

首先导入需要的库。

每个库在本爬虫代码中的用处在注释中已经标注。

import requests                      # 发起网络请求
from bs4 import BeautifulSoup       # 解析HTML文本
import pandas as pd                 # 处理数据
import os
import time         # 处理时间戳
import json         # 用来解析json文本

发起网络请求函数 fetchUrl

函数用途及三个参数的含义,已在代码注释中标注,返回值为 json 类型的数据

'''
用于发起网络请求
url : Request Url
kw  : Keyword
page: Page number
'''
def fetchUrl(url, kw, page):# 请求头headers={"Accept": "application/json, text/plain, */*","Content-Type": "application/json;charset=UTF-8","User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Safari/537.36",}# 请求参数payloads = {"endTime": 0,"hasContent": True,"hasTitle": True,"isFuzzy": True,"key": kw,"limit": 10,"page": page,"sortType": 2,"startTime": 0,"type": 0,}# 发起 post 请求r = requests.post(url, headers=headers, data=json.dumps(payloads))return r.json()

数据解析函数 parseJson

解析 json 对象,然后将解析到的数据包装成数组返回

def parseJson(jsonObj):#解析数据records = jsonObj["data"]["records"];for item in records:# 这里示例解析了几条,其他数据项如末尾所示,有需要自行解析pid = item["id"]originalName = item["originalName"]belongsName = item["belongsName"]content = BeautifulSoup(item["content"], "html.parser").textdisplayTime = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(item["displayTime"]/1000))subtitle = item["subtitle"]title = BeautifulSoup(item["title"], "html.parser").texturl = item["url"]yield [[pid, title, subtitle, displayTime, originalName, belongsName, content, url]]

数据保存函数 saveFile

'''
用于将数据保存成 csv 格式的文件(以追加的模式)
path   : 保存的路径,若文件夹不存在,则自动创建
filename: 保存的文件名
data   : 保存的数据内容
'''
def saveFile(path, filename, data):# 如果路径不存在,就创建路径if not os.path.exists(path):os.makedirs(path)# 保存数据dataframe = pd.DataFrame(data)dataframe.to_csv(path + filename + ".csv", encoding='utf_8_sig', mode='a', index=False, sep=',', header=False )

主函数

if __name__ == "__main__":# 起始页,终止页,关键词设置start = 1end = 3kw = "春节"# 保存表头行headline = [["文章id", "标题", "副标题", "发表时间", "来源", "版面", "摘要", "链接"]]saveFile("./data/", kw, headline)#爬取数据for page in range(start, end + 1):url = "http://search.people.cn/api-search/elasticSearch/search"html = fetchUrl(url, kw, page)for data in parseJson(html):saveFile("./data/", kw, data)print("第{}页爬取完成".format(page))# 爬虫完成提示信息print("爬虫执行完毕!数据已保存至以下路径中,请查看!")print(os.getcwd(), "\\data")

以上为本爬虫的全部代码,大家可以在此基础上进行修改来使用,仅供学习交流,切勿用于违法用途。

注:这里没有写正文爬取的代码,一是人民网文章正文爬取的函数在上一篇文章中已经写了,大家有需要的话可以自行整合代码;二是,爬取正文的话会引入一些其他的问题,比如链接失效,文章来源于不同网站,解析方式不同等问题,说来话长,本文主要以思路讲解为主。

1.4 成果展示

1.4.1 程序运行效果

1.4.2 爬到的数据展示

2. 利用现有数据筛选

如果你已经提前下载到了全部的新闻文章数据,那用这种方法无疑是最方便的,省去了漫长的爬取数据的过程,也省得跟反爬机制斗智斗勇。

2.1 数据来源

下载地址:https://github.com/caspiankexin/people-daily-crawler-date

以上是一个读者朋友爬取的人民日报新闻数据,包含从 19 年起至今的数据,每月一更新,应该可以满足很大一部分人对数据的需求了。

此外我还有之前爬的 18 年全年的数据,如果有需要的朋友,可以私聊找我要。

2.2 检索代码

以如下图所示的目录结构为例。

假设我们有一些关键词,需要检测这些新闻文章中哪篇包含有关键词。

import os# 这里是你文件的根目录
path = "D:\\Newpaper\\2018"# 遍历path路径下的所有文件(包括子文件夹下的文件)
def iterFilename(path):#将os.walk在元素中提取的值,分别放到root(根目录),dirs(目录名),files(文件名)中。for root, dirs, files in os.walk(path):for file in files:# 根目录与文件名组合,形成绝对路径。yield os.path.join(root,file)# 检查文件中是否包含关键词,若包含返回True, 若不包含返回False
def checkKeyword(filename, kwList):with open(filename, "r", encoding="utf-8") as f:content = f.read()for kw in kwList:if kw in content:return True, kwreturn False, ""if __name__ == "__main__":# 关键词数组kwList = ["经济", "贸易"]#遍历文章for file in iterFilename(path):res, kw = checkKeyword(file, kwList)if res:# 如果包含关键词,打印文件名和匹配到的关键词print("文件 ", file," 中包含关键词 ", kw)

2.3 运行结果

运行程序,即可从文件中筛选出包含关键词的文章。


2021年9月9日更新

最近有读者在复现文中的爬虫时,发现有如下报错:

in parseJson records = jsonObj[“data”][“records”];
TypeError:“data”

经过调试检查后,发现这个报错是因为原网站中,关键词搜索的接口更换了,导致数据获取失败。

解决办法:

将主函数部分的 url 替换成新的接口 http://search.people.cn/api-search/front/search 即可,如下所示。

if __name__ == "__main__":# 起始页,终止页,关键词设置start = 1end = 3kw = "春节"# 保存表头行headline = [["文章id", "标题", "副标题", "发表时间", "来源", "版面", "摘要", "链接"]]saveFile("./data/", kw, headline)#爬取数据for page in range(start, end + 1):# url = "http://search.people.cn/api-search/elasticSearch/search"url = "http://search.people.cn/api-search/front/search"html = fetchUrl(url, kw, page)for data in parseJson(html):saveFile("./data/", kw, data)print("第{}页爬取完成".format(page))# 爬虫完成提示信息print("爬虫执行完毕!数据已保存至以下路径中,请查看!")print(os.getcwd(), "\\data")

2021年12月13日更新

最近有读者反馈,程序运行又报错了,可能是网站那个接口又换了。

我查看了一下,确实是这样。

只需要将接口替换为 http://search.people.cn/search-platform/front/search 即可,替换方法同上。


如果文章中有哪里没有讲明白,或者讲解有误的地方,欢迎在评论区批评指正,或者扫描下面的二维码,加我微信,大家一起学习交流,共同进步。

Python爬虫实战 | 人民网爬虫 根据关键词筛选新闻文章相关推荐

  1. Python爬虫实战:爬取解放日报新闻文章

    上一篇<Python 网络爬虫实战:爬取人民日报新闻文章>发布之后,确实帮到了不少朋友. 前几天,我好哥们问我:我想爬另一个日报新闻网站,网页结构几乎跟人民日报几乎一模一样,但是我用你的那 ...

  2. python爬网易新闻_Python爬虫实战教程:爬取网易新闻;爬虫精选 高手技巧

    Python爬虫实战教程:爬取网易新闻:爬虫精选 高手技巧 发布时间:2020-02-21 17:42:43 前言本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有, ...

  3. Qt与Python脚本实战之一(爬虫)

    Qt与Python脚本实战之一(爬虫) Python环境安装 1.Python版本选择(2.7 or 3.6.x) 版本不同区别蛮大 2.安装pip 一个Python包管理工具 类似nodejs的np ...

  4. python爬虫实战,爬虫之路,永无止境

    python爬虫实战 好久没给大家跟新爬虫文章了,抱歉抱歉,这期给大家带来一篇小爬虫,希望大家喜欢,喜欢的来个关注,支持一下博主,谢谢各位了. 写代码了各位宝宝们 这里要注意一点就是要记得提前登录,c ...

  5. 爬虫实战之爬虫漫画(复现)

    目录 爬虫实战---动态网页内部加载 复现爬虫漫画 思路 所有章节的标题和URL 找到所有章节漫画内容 保存漫画 爬虫实战-动态网页内部加载 动态网页的爬取和静态网页的爬取不一样,静态网页我们想要的资 ...

  6. 爬虫实战:通过百度关键词爬取大量图片

    目标地址: http://image.baidu.com/ 输入美女 分析网址 元网址见图 粘贴过来却如下 (在这里你会看到,明明在浏览器URL栏看到的是中文,但是复制url,粘贴到记事本或代码里面, ...

  7. Python爬虫实战项目:简单的百度新闻爬虫

    这个实战例子是构建一个大规模的异步新闻爬虫,但要分几步走,从简单到复杂,循序渐进的来构建这个Python爬虫 本教程所有代码以Python 3.6实现,不兼顾Python 2,强烈建议大家使用Pyth ...

  8. 入门小远学爬虫(二)(四)简单GET型网页爬虫实战——“前程无忧”爬虫岗位信息的爬取之正则概念以及Python中re库的简单应用

    文章目录 前言 一.正则表达式是什么? 二.正则表达式语法 1.简介 2.干货分享 三.re库 1.安装 2.用法 四.终于进入正题 小结 前言 这是本系列第一个实战项目的第四课,有关前三课相关的内容 ...

  9. python爬网易新闻_Python爬虫实战教程:爬取网易新闻

    前言 本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,版权归原作者所有,如有问题请及时联系我们以作处理. 作者: Amauri PS:如有需要Python学习资料的小伙伴可以加点击 ...

  10. python微博爬虫实战_Python爬虫实战演练:爬取微博大V的评论数据

    本文的文字及图片来源于网络,仅供学习.交流使用,不具有任何商业用途,如有问题请及时联系我们以作处理. 以下文章来源于IT共享之家 ,作者: IT共享者 理论篇 试想一个问题,如果我们要抓取某个微博大V ...

最新文章

  1. 使用Python,OpenCV加载图像并将其显示在屏幕上?
  2. java迷宫生成代码_通过深度优先搜索产生的迷宫的Java代码
  3. getChars的用法
  4. 深入理解计算机系统之旅(一)计算机系统漫游
  5. PHP原生类反序列化
  6. python异步处理请求_如何一次在python中发送异步http请求?
  7. Hadoop集群环境下网络架构的设计与优化
  8. linux shell 脚本路径,linux获取shell脚本所在绝对路径操作介绍
  9. Java基础学习总结(161)——Java 重试机制
  10. thinkphp __hash__
  11. 3.TCP/IP 详解卷1 --- IP:网际协议
  12. 基于java开发的网上商城系统
  13. 中企动力助天正生物争夺破伤风抗毒素全球话语权
  14. ORA-00932: 数据类型不一致: 应为 NUMBER, 但却获得 BINARY
  15. uniapp字体图标的使用
  16. 你为什么需要认知升级?认知决定你的财富!
  17. 前端超出文字显示省略号
  18. iOS新特性框架、仿微信图片浏览、视频监控、爱心动画、文字适配等源码
  19. 关于Revit 插件Add-in Manager安装问题
  20. linux中级工程师面试题,Linux运维中级工程师面试题

热门文章

  1. 实验8人机交互页面的创新设计
  2. 解决:远程服务器(阿里云 VHost)和本地文件传输 windows
  3. 安装cygwin软件
  4. 谁要的手机用KRKR2 Onscripter 资源打包工具
  5. 作为股权类投资人,我们的投资偏好和投资原则
  6. discuz3x ucenter 与cas 初步整合
  7. 如何用python爬虫薅羊毛_拼多多现重大BUG被“薅羊毛”,教你如何用Python简单褥羊毛...
  8. OSS对象存储是什么?
  9. 图能页:傻瓜式的手机网页制作服务
  10. 自由与钱无关,限制你的只是自己的格局——北漂18年(77)