网页新闻抓取(如何用Python新闻利用BeautifulSoup分析HTML的应用?(组图))

优采云 发布时间: 2021-10-01 02:24

  网页新闻抓取(如何用Python新闻利用BeautifulSoup分析HTML的应用?(组图))

  每天坐地铁上班,地铁信号差。但是我想一边坐地铁一边看新闻,所以写了下面这个新闻爬虫。没打算做一个漂亮的应用,所以只完成了原型,可以满足我最基本的需求。这个想法很简单:

  寻找新闻来源;使用Python抓取新闻;使用 BeautifulSoup 分析 HTML 并提取内容;将其转换为易于阅读的格式并通过电子邮件发送。

  下面详细介绍各个部分的实现。

  新闻来源:Reddit

  我们可以通过 Reddit 提交新闻链接并投票,所以 Reddit 是一个很好的新闻来源。但接下来的问题是:我们如何才能每天获得最热门的新闻?在考虑爬取之前,首先要考虑目标网站是否提供了API。因为使用 API 是完全合法的,更重要的是它可以提供机器可读的数据,所以不需要分析 HTML。幸运的是,Reddit 提供了一个 API。我们可以从 API 列表中找到所需的函数:/top。此函数可以返回 Reddit 或指定 subreddit 上最流行的新闻。下一个问题是:如何使用这个API?仔细阅读Reddit文档后,我发现了最有效的用法。第 1 步:在 Reddit 上创建一个应用程序。登录后,进入“偏好设置→应用程序”页面,有一个名为“的按钮”

  

  创建应用后,可以在应用信息中找到App ID和Secret。

  

  接下来的问题是如何使用App ID和Secret。由于我们只需要获取指定SubReddit上最热门的新闻,而无需访问任何与用户相关的信息,因此理论上我们不需要提供用户名或密码等个人信息。Reddit 提供了“Application Only OAuth”(#application-only-oauth)的形式。通过这种方式,应用程序可以匿名访问公共信息。运行以下命令:

  $ curl -X POST -H 'User-Agent: myawesomeapp/1.0' -d grant_type=client_credentials --user 'OUR_CLIENT_ID:OUR_CLIENT_SECRET'  https://www.reddit.com/api/v1/access_token 

  此命令将返回访问令牌:

  {"access_token": "ABCDEFabcdef0123456789", "token_type": "bearer", "expires_in": 3600, "scope": "*"} 

  伟大的!获得访问令牌后,您就可以大展身手了。最后,如果不想自己写API访问代码,可以使用Python客户端:先做个测试,从/r/Python获取5条最流行的消息:

  >>> import praw >>> import pprint >>> reddit = praw.Reddit(client_id='OUR_CLIENT_ID', ...                      client_secret='OUR_SECRET', ...                      grant_type='client_credentials', ...                      user_agent='mytestscript/1.0') >>> subs = reddit.subreddit('Python').top(limit=5) >>> pprint.pprint([(s.score, s.title) for s in subs]) [(6555, 'Automate the boring stuff with python - tinder'),  (4548,   'MS is considering official Python integration with Excel, and is asking for '   'input'),  (4102, 'Python Cheet Sheet for begineers'),  (3285,   'We started late, but we managed to leave Python footprint on r/place!'),  (2899, "Python Section at Foyle's, London")] 

  它成功了!

  抓取新闻页面

  接下来的任务是抓取新闻页面,其实很简单。通过上一步,我们可以得到Submission对象,其URL属性就是新闻的地址。我们还可以通过 domain 属性过滤掉属于 Reddit 的 URL:

  subs = [sub for sub in subs if not sub.domain.startswith('self.')] 

  我们只需要抓取 URL,这可以通过 Requests 轻松完成:

  for sub in subs:   res = requests.get(sub.url)   if (res.status_code == 200 and 'content-type' in res.headers and       res.headers.get('content-type').startswith('text/html')):     html = res.text 

  这里我们跳过了内容类型不是 text/html 的新闻地址,因为 Reddit 用户可能会提交直接指向图片的链接,而我们不需要这个。

  提取新闻内容

  下一步是从 HTML 中提取内容。我们的目标是提取新闻的标题和正文,可以忽略其他不需要阅读的内容,例如页眉、页脚、侧边栏等。这项工作很难,没有通用的解决方案。虽然 BeautifulSoup 可以帮助我们提取文本内容,但它会一起提取第一页页脚。幸运的是,我发现网站的当前结构比以前好很多。没有表格布局,没有总和

  , 整个 文章 页面清楚地使用和

  标题和每个段落都有标记。而大多数 网站 会将标题和正文放在同一个容器元素中,例如,像这样:

  Site Navigation         Page Title           <p>Paragraph 1     

  Paragraph 2     Sidebar Copyright... </p>

  本例中的顶级

  它是标题和正文的容器。因此,您可以使用以下算法来查找文本:

  虽然这个算法很初级,没有考虑任何语义信息,但它是完全可行的。毕竟当算法失败时,只需要忽略文章,少读一个文章。没什么大不了的……当然你可以通过解析来实现,或者#main、.sidebar等语义元素。实现更准确的算法。使用此算法,您可以轻松编写解析代码:

  soup = BeautifulSoup(text, 'html.parser') # find the article title h1 = soup.body.find('h1') # find the common parent for  and all <p>s. root = h1 while root.name != 'body' and len(root.find_all('p'))  done, title = "SMS Spoofing with Python for Good and Evil"   ... 

  抓取的新闻文件:

  

  最后要做的就是把这个脚本放到服务器上,设置cronjob每天运行一次,然后把生成的文件发送到我的邮箱。我没有花太多时间去关注细节,所以其实这个脚本还有很多需要改进的地方。如果有兴趣,可以继续添加更*敏*感*词*,比如提取图片。

  【编辑推荐】

  为什么程序员和开发者应该在 2020 年学习 Python 魔术操作:教你使用 Python 识别恶意软件以及为什么你的 Python 代码应该是扁平和稀疏的。使用 Python 构建您自己的 Markdown 编辑器。Python炫操作(02):七种合并字典的方法

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线