使用Python进行网页抓取

作者 : IT 大叔 本文共3427个字,预计阅读时间需要9分钟 发布时间: 2020-11-9

有时,您想访问Web上无法通过API轻松访问的数据。本质上,网络抓取是一种以编程方式访问网站的方式,就好像您是浏览器一样,并以这种方式获取数据。本教程文章将指导您使用Python3以及两个库BeautifulSoupRequests进行Web抓取过程。例如,我们将构建一个命令行应用程序,以在IMDB上搜索和打印电影和电视节目的评级。


项目设置

要继续学习本教程,您需要具备以下条件:

  • 安装了Python
  • 一些Python基本知识和一些HTML / CSS基本知识

首先,为项目创建一个文件夹并安装所需的依赖项:

复制
mkdir web-scrape
cd web-scrape
pip3 install beautifulsoup4 requests
  • beautifulsoup4 让我们轻松地以编程方式访问DOM元素
  • requests 为我们提供了一个易于使用的界面来发出HTTP请求

研究应用程序的生命周期

如引言中所述,我们将专注于搜索IMDB,以显示某些选定标题的等级。我们的第一步应该是在浏览器中执行这些步骤,并在其中查看外观。

在浏览器中访问www.imdb.com并搜索您选择的电影。我在侏罗纪公园Jurassic Park)中进行了搜索,您应该会看到类似下面的图片:

使用Python进行网页抓取插图

进入此页面后,右键单击并按“检查元素”检查“标题”表中的行之一,这随浏览器的不同而不同,但是在Firefox中看起来像这样:

使用Python进行网页抓取插图(2)

您可能还已经注意到,浏览器底部打开了一些内容,该部分通常称为开发工具。现在,我们将使用它来确定所要获取的数据的结构。在撰写本文时,它看起来像这样:

使用Python进行网页抓取插图(4)

这里显示的是DOM结构。此处突出显示的行是我之前执行“检查元素”操作时选择的行。这向我们展示了所有HTML节点如何相互关联以及我们所要查找的数据在DOM中的位置。由于我们希望能够在我们的应用程序中列出这些结果,因此我们需要能够显示这些搜索结果。

我们可以看到,我们感兴趣的数据位于<td>class类的元素内result_text,标题的名称被包装在一个<a>元素中,并且href具有指向标题的相对链接。这是我们从此页面需要的所有数据。

让我们单击该标题的链接,以查看我们需要处理的下一页的外观,单击指向其中一个搜索结果的链接,您应该在选择的电影/节目的页面上结束:

使用Python进行网页抓取插图(6)

在此页面上时,让我们重复步骤并在评级显示上“检查元素”

使用Python进行网页抓取插图(8)使用Python进行网页抓取插图(10)

在这里,我们可以看到,对于此页面,我们感兴趣的数据位于由span元素包装的strong元素内部,而元素又由div具有类的元素包装ratingValue

现在,我们已经收集了应用程序所需的所有信息,让我们继续进行编码部分。


在IMDB上搜索并列出标题

创建一个文件scrape.py,这将是我们针对该项目的唯一文件。在其中,我们将首先导入所需的依赖项并添加搜索功能:

复制
# scrape.py
import requests
from bs4 import BeautifulSoup

def search(search_term):
    # Make the search request to IMDB
    response = requests.get(f"https://www.imdb.com/find?q={search_term}")
    html = response.text
    soup = BeautifulSoup(html, "html.parser")
    # Find the table with the class findList
    table = soup.find("table", {"class": "findList"})
    # Use CSS selector syntax to get all td elements from the table with the class result_text
    rows = table.select("tr td.result_text")
    # Construct a list with the search results, store the title and the href in dicts
    return [{"title": row.get_text().strip(), "href": row.a['href']} for row in rows]

让我们向该文件添加另一个函数,在该函数中放置用户交互代码:

复制
def run():
    search_term = input("Search IMDB: ")
    results = search(search_term)
    num_results = len(results)
    print(f"Found {num_results} results:")
    # Use built-in function enumerate to access the index variable i
    for i, result in enumerate(results):
        print(f"({i+1}) {result['title']}")

# Don't forget this line! We have to call the run function or nothing will happen when we run our program.
run()

保存文件,我们准备尝试我们的应用程序以查看它的外观,然后通过进入终端并运行该文件来运行它:

复制
python3 scrape.py

输入搜索词,应该会出现类似的内容:

使用Python进行网页抓取插图(12)

您可能会注意到,选择结果目前无济于事,这是因为我们只实现了一半的逻辑。最好测试一下到目前为止所能完成的工作,如果您在终端中看到搜索结果,则可以继续进行。


打印所选标题的等级

我们需要更多逻辑来请求下一页并打印span我们先前标识的元素中的值。您可能已经注意到,在search定义的函数中,我们返回hrefs,但尚未使用它们。现在将它们合并。

在中scrape.py,添加另一个功能:

复制
def get_rating(href):
    # href passed in here should be from what we found earlier, the href from the <a> tag that the title was wrapped in
    response = requests.get(f"https://www.imdb.com{href}")
    html = response.text
    soup = BeautifulSoup(html, "html.parser")
    # Select by CSS selector for .ratingValue class and get the first result (index 0), we only expect there to be one
    rating = soup.select(".ratingValue")[0].span.get_text()
    return rating

让我们在run函数中使用它:

复制
def run():
    # Main interaction
    search_term = input("Search IMDB: ")
    results = search(search_term)
    num_results = len(results)

    print(f"Found {num_results} results:")
    for i, result in enumerate(results):
        print(f"({i+1}) {result['title']}")

    # Convert to int and subtract one to undo the addition to the index in the above loop
    selection = int(input(f"Select by entering a number (1-{num_results}): ")) - 1
    selected_result = results[selection]
    # Pass in the href to the title we want to get the rating for
    rating = get_rating(selected_result["href"])

    print(f"{selected_result['title']} has a rating of {rating}!")

# Again, make sure you call this in scrape.py
run()

现在运行我们的应用程序将导致以下行为:

使用Python进行网页抓取插图(14)


概要

如果您可以使用API​​来获取所要获取的数据,则应该始终这样做,这样可以更快,更不容易出错。有时,根据DOM的结构,爬网可能会变得凌乱。您可能已经知道,如果要更改IMDB的布局,则可能会破坏我们的应用程序。

免责声明:
1. 本站资源转自互联网,源码资源分享仅供交流学习,下载后切勿用于商业用途,否则开发者追究责任与本站无关!
2. 本站使用「署名 4.0 国际」创作协议,可自由转载、引用,但需署名原版权作者且注明文章出处
3. 未登录无法下载,登录使用金币下载所有资源。
IT小站 » 使用Python进行网页抓取

常见问题FAQ

没有金币/金币不足 怎么办?
本站已开通每日签到送金币,每日签到赠送五枚金币,金币可累积。
所有资源普通会员都能下载吗?
本站所有资源普通会员都可以下载,需要消耗金币下载的白金会员资源,通过每日签到,即可获取免费金币,金币可累积使用。

发表评论