Python 30 天 – 第 23 天 – 网页抓取(python爬虫网站抓取)

作者 : 慕源网 本文共5151个字,预计阅读时间需要13分钟 发布时间: 2021-10-14 共94人阅读

Python 30 天 - 第 23 天 - 网页抓取(python爬虫网站抓取)

本文是 30 天 Python 挑战系列的一部分。您可以在此处找到本系列之前所有帖子的链接

Web Scraping 是一种通过抓取网站从网站中提取数据的技术。它主要用于从网站收集有意义的数据,特别是当没有可用的 API 来提取信息时。今天我探索了使用 Python 进行网页抓取的基础知识,并想分享我的经验。

Scraping 是一种脚本形式,它使我们能够自动化从网站中提取大量非结构化数据的过程,并以结构化的方式组织它以将其用于多种目的,例如收集电子邮件、产品价格、股票价格、航班数据或任何其他相关信息。手动执行这些操作需要花费大量时间和精力。Python 有一些很棒的库,可以使网络抓取变得非常容易和有趣。我主要探索了最基本和最受欢迎的库 Beautiful Soup 来熟悉这个概念。

Web Scraping 非常强大,关于它的用途有很多争论。大多数网站都有一个 robots.txt 文件,其中提到应该抓取(抓取)哪些特定 URL,哪些不应该抓取。该文件主要是针对各种搜索引擎机器人(如 Google bot、Yahoo bot、Bing bot 等)应抓取哪些特定页面以进行搜索引擎优化的指令。因此,所有搜索引擎爬虫主要是网络爬虫,它们从网站中提取数据,根据相关关键字对它们进行排名。

但是,即使 robots.txt 文件中不允许,网站也不能严格限制网络抓取程序不抓取其数据。浏览网站的 robots.txt 文件(如果存在)并仅从提及的 URL 中提取数据以防止任何类型的数据泄露问题。

Beautiful Soup

在今天的课程中,我决定尝试从 Hacker News 网站(开发人员社区中非常受欢迎的网站)中提取数据。这些是在其 robots.txt 文件中定义的规则

User-Agent: *     
Disallow: /x?    
Disallow: /vote?    
Disallow: /reply?    
Disallow: /submitted?    
Disallow: /submitlink?    
Disallow: /threads?    
Crawl-delay: 30 

因此,我们被允许从新闻页面 https://news.ycombinator.com/newest 抓取和获取数据,该页面列出了来自开发世界的最新文章。目标是抓取前 5 页并提取至少 100 分的文章及其链接。这对于自动获取所有高投票项目并从终端本身读取它们非常有用,而无需访问黑客新闻网站并手动搜索热门帖子。

需要安装前两个库,requests 用于执行 HTTP 请求,beautifulsoup4 用于抓取网站。

pip install 请求 pip install beautifulsoup4

hacker_news_scraper.py

import requests    
from bs4 import BeautifulSoup    
    
BASE_URL = 'https://news.ycombinator.com'    
response = requests.get(BASE_URL)    
# 提取网页的文本内容    
response_text = response.text    
# 解析 HTML    
soup = BeautifulSoup(response_text, 'html.parser')    
print(soup.prettify()) # prints the html content in a readable format 

Beautiful Soup 的文档 https://www.crummy.com/software/BeautifulSoup/bs4/doc/ 展示了各种用例。使用浏览器的检查元素工具,可以查看元素的选择器,然后用于提取数据。在这种情况下,所有文章都有一个 storylink 类,它们的关联点有类分数。现在可以使用这些选择器来获取相应的数据并将它们组合起来。

# 使用类选择器提取所有链接    
links_list = soup.select('.storylink')    
    
# 使用类选择器提取所有点    
points_list = soup.select('.score')  

循环遍历链接后,关联的、标题、链接和它们的点可以组合为字典对象,然后附加到流行的帖子列表中。

需要注意的是,enumerate 函数用于获取每个元素的索引以获取相应的点,因为这些点不包含在链接容器中。

只有至少 100 分的帖子才会添加到热门列表中。

# loop though all links    
for idx, link in enumerate(links_list):    
    # fetch the title of the post    
    post_title = link.get_text()    
    # fetch the link of the post    
    post_href = link.get('href')    
    # fetch the point text using the index of the link    
    # convert the point to integer    
    post_points = int(points_list[idx].get_text().replace(' points', ''))    
    # append to popular posts as a dictionary object if points is atleast 100    
    if post_points >= 100:    
        popular_posts.append(    
        {'title': post_title, 'link': post_href, 'points': post_points})    

有一个有用的内置 Python 库 pprint 可以以更易读的格式在控制台中打印数据。

import pprint   

然后可用于查看流行列表

# loop though all links    
for idx, link in enumerate(links_list):    
    # fetch the title of the post    
    post_title = link.get_text()    
    # fetch the link of the post    
    post_href = link.get('href')    
    # fetch the point text using the index of the link    
    # convert the point to integer    
    post_points = int(points_list[idx].get_text().replace(' points', ''))    
    # append to popular posts as a dictionary object if points is atleast 100    
    if post_points >= 100:    
        popular_posts.append(    
        {'title': post_title, 'link': post_href, 'points': post_points})  

上述脚本仅从 Hacker News 的第一页获取热门帖子。但是,根据所需的目标,我们需要从前五页或可能输入的任何页数中获取列表。因此可以相应地修改脚本。

import requests    
from bs4 import BeautifulSoup    
import pprint    
import time    
    
BASE_URL = 'https://news.ycombinator.com'    
# response = requests.get(BASE_URL)    
    
def get_lists_and_points(soup):    
    # extract all the links using the class selector    
    links_list = soup.select('.storylink')    
    
    # extract all the points using the class selector    
    points_list = soup.select('.score')    
    
    return (links_list, points_list)    
    
def parse_response(response):    
    # extract the text content of the web page    
    response_text = response.text    
    # parse HTML    
    soup = BeautifulSoup(response_text, 'html.parser')    
    return soup    
    
def get_paginated_data(pages):    
    total_links_list = []    
    total_points_list = []    
    for page in range(pages):    
        URL = BASE_URL + f'?p={page+1}'    
        response = requests.get(URL)    
        soup = parse_response(response)    
        links_list, points_list = get_lists_and_points(soup)    
        for link in links_list:    
            total_links_list.append(link)    
        for point in points_list:    
            total_points_list.append(point)    
        # add 30 seconds delay as per hacker news robots.txt rules    
        time.sleep(30)    
    return (total_links_list, total_points_list)    
    
def generate_popular_posts(links_list, points_list):    
    # create an empty popular posts list    
    popular_posts = []    
    
    # loop though all links    
    for idx, link in enumerate(links_list):    
        # fetch the title of the post    
        post_title = link.get_text()    
        # fetch the link of the post    
        post_href = link.get('href')    
        # fetch the point text using the index of the link    
        # convert the point to integer    
        # if points data is not available, assign it a default of 0    
        try:    
            post_points = int(    
                points_list[idx].get_text().replace(' points', ''))    
        except:    
            points_list = 0    
        # append to popular posts as a dictionary object if points is atleast 100    
        if post_points >= 100:    
            popular_posts.append(    
                {'title': post_title, 'link': post_href, 'points': post_points})    
    return popular_posts    
    
def sort_posts_by_points(posts):    
    return sorted(posts, key=lambda x: x['points'], reverse=True)    
    
def main():    
    total_links_list, total_points_list = get_paginated_data(5)    
    popular_posts = generate_popular_posts(total_links_list, total_points_list)    
    sorted_posts = sort_posts_by_points(popular_posts)    
    # print posts sorted by highest to lowest    
    pprint.pprint(sorted_posts)    
    
if(__name__ == '__main__'):    
    main()    

现在使用这个脚本,我们甚至不需要访问 Hacker News 和搜索热门新闻。我们可以从控制台运行此脚本并获取最新消息。随意根据您的需要调整脚本并对其进行试验或尝试从您自己喜欢的网站上抓取数据。

我们可以用上面的数据做很多事情,比如

  • 创建一个 API 以将其用于网站应用程序
  • 使用它来使用关键字分析趋势
  • 创建新闻聚合网站等

流行的爬虫库

Beautiful Soup 在从网站上抓取数据时有其限制。它使用起来非常简单,但是为了从在客户端呈现的复杂网站(Angular、基于 React 的网站)中抓取数据,当网站加载时 HTML 标记将不可用。要从此类网站获取数据,可以使用更高级的库。以下是一些流行的 Python 库和框架。

  • lxml
  • Selenium
  • Scrapy – It is a complete framework for web scraping

网页抓取是一个广阔的领域。使用 Beautiful Soup,我们可能只是触及了表面。在这个领域有很多可能性,我将在探索更多关于使用 Python 的数据分析的同时进行探索。希望我已经能够涵盖进一步探索所需的基本概念。

明天我将讨论使用 Python 进行 Web 开发的概念。


慕源网 » Python 30 天 – 第 23 天 – 网页抓取(python爬虫网站抓取)

常见问题FAQ

免费下载或者VIP会员专享资源能否直接商用?
本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。

发表评论

开通VIP 享更多特权,建议使用QQ登录