📌  相关文章
📜  如何使用Python抓取网站的多个页面?

📅  最后修改于: 2022-05-13 01:55:36.552000             🧑  作者: Mango

如何使用Python抓取网站的多个页面?

Web Scraping 是一种使用计算机程序从网站中提取有用数据的方法,而无需手动进行。然后可以出于各种目的导出和分类组织这些数据。 Web Scraping 的一些常见用途是市场研究和分析网站、价格比较工具、搜索引擎、AI/ML 项目的数据收集等。

让我们深入研究并抓取一个网站。在本文中,我们将使用 GeeksforGeeks 网站并使用Python脚本提取主页上所有可用文章的标题。

如果您注意到,网站上有数以千计的文章,要提取所有文章,我们将不得不浏览所有页面,以免错过任何文章!

GeeksforGeeks 主页

使用Python抓取网站的多个页面

现在,可能会出现各种情况,您可能希望从同一网站的多个页面或多个不同的 URL 获取数据,并且为每个网页手动编写代码是一项耗时且乏味的任务。此外,它违背了自动化的所有基本原则。呸!

为了解决这个确切的问题,我们将看到两种主要技术可以帮助我们从多个网页中提取数据:



  • 同一个网站
  • 不同的网址

方法:

该程序的方法将相当简单,并且以 POINT 格式更容易理解:

  • 我们将导入所有必要的库
  • 设置我们的 URL字符串以使用请求库建立连接。
  • 使用BeautifulSoup库的解析器从目标页面解析可用数据。
  • 从目标页面,识别提取包含对我们有价值的信息的类和标签。
  • 使用循环为一页制作原型,然后将其应用于所有页面。

示例 1:循环遍历页码

GeeksforGeeks 网站底部的页码

大多数网站都有从 1 到 N 标记的页面。这使得我们可以很容易地遍历这些页面并从中提取数据,因为这些页面具有相似的结构。例如:

注意 URL 的最后一部分 – page/4/

在这里,我们可以在 URL 的末尾看到页面详细信息。使用这些信息,我们可以轻松地创建一个for 循环,遍历任意数量的页面(通过将page/(i)/放在 URL字符串并迭代“ i直到 N )并从中抓取所有有用的数据。以下代码将使您更清楚地了解如何在Python使用For 循环来抓取数据。

Python
import requests
from bs4 import BeautifulSoup as bs
  
URL = 'https://www.geeksforgeeks.org/page/1/'
  
req = requests.get(URL)
soup = bs(req.text, 'html.parser')
  
titles = soup.find_all('div',attrs = {'class','head'})
  
print(titles[4].text)


Python
import requests
from bs4 import BeautifulSoup as bs
  
URL = 'https://www.geeksforgeeks.org/page/'
  
for page in range(1,10):
      # pls note that the total number of
    # pages in the website is more than 5000 so i'm only taking the
    # first 10 as this is just an example
  
    req = requests.get(URL + str(page) + '/')
    soup = bs(req.text, 'html.parser')
  
    titles = soup.find_all('div',attrs={'class','head'})
  
    for i in range(4,19):
        if page>1:
            print(f"{(i-3)+page*15}" + titles[i].text)
        else:
            print(f"{i-3}" + titles[i].text)


Python
import requests
from bs4 import BeautifulSoup as bs
URL = ['https://www.geeksforgeeks.org','https://www.geeksforgeeks.org/page/10/']
  
for url in range(0,2):
    req = requests.get(URL[url])
    soup = bs(req.text, 'html.parser')
  
    titles = soup.find_all('div',attrs={'class','head'})
    for i in range(4, 19):
        if url+1  > 1:
            print(f"{(i - 3) + url * 15}" + titles[i].text)
        else:
            print(f"{i - 3}" + titles[i].text)


Python3
from random import randint
from time import sleep 
  
print(randint(1,10))


Python3
from time import *
from random import randint
  
for i in range(0,3):
  # selects random integer in given range
  x = randint(2,5)
  print(x)
  sleep(x)
  print(f'I waited {x} seconds')


Python3
import requests
from bs4 import BeautifulSoup as bs
from random import randint
from time import sleep
  
URL = 'https://www.geeksforgeeks.org/page/'
  
for page in range(1,10): 
      # pls note that the total number of
    # pages in the website is more than 5000 so i'm only taking the
    # first 10 as this is just an example
  
    req = requests.get(URL + str(page) + '/')
    soup = bs(req.text, 'html.parser')
  
    titles = soup.find_all('div',attrs={'class','head'})
  
    for i in range(4,19):
        if page>1:
            print(f"{(i-3)+page*15}" + titles[i].text)
        else:
            print(f"{i-3}" + titles[i].text)
  
    sleep(randint(2,10))


输出:

上述代码的输出

现在,使用上面的代码,我们可以通过用循环将这些行夹在中间来获得所有文章的标题。



Python

import requests
from bs4 import BeautifulSoup as bs
  
URL = 'https://www.geeksforgeeks.org/page/'
  
for page in range(1,10):
      # pls note that the total number of
    # pages in the website is more than 5000 so i'm only taking the
    # first 10 as this is just an example
  
    req = requests.get(URL + str(page) + '/')
    soup = bs(req.text, 'html.parser')
  
    titles = soup.find_all('div',attrs={'class','head'})
  
    for i in range(4,19):
        if page>1:
            print(f"{(i-3)+page*15}" + titles[i].text)
        else:
            print(f"{i-3}" + titles[i].text)

输出:

上述代码的输出

注意:上面的代码将从网站上获取前 10 个页面,并抓取这些页面下所有 150 个文章的标题。

示例 2:循环遍历不同 URL 的列表。

上面的技巧绝对很棒,但是如果您需要抓取不同的页面,而您不知道它们的页码怎么办?您需要一一抓取这些不同的 URL,并为每个此类网页手动编写脚本。

相反,您可以只列出这些 URL 并循环遍历它们。通过简单地迭代列表中的项目,即 URL,我们将能够提取这些页面的标题,而无需为每个页面编写代码。这是您如何做到这一点的示例代码。

Python

import requests
from bs4 import BeautifulSoup as bs
URL = ['https://www.geeksforgeeks.org','https://www.geeksforgeeks.org/page/10/']
  
for url in range(0,2):
    req = requests.get(URL[url])
    soup = bs(req.text, 'html.parser')
  
    titles = soup.find_all('div',attrs={'class','head'})
    for i in range(4, 19):
        if url+1  > 1:
            print(f"{(i - 3) + url * 15}" + titles[i].text)
        else:
            print(f"{i - 3}" + titles[i].text)

输出:

上述代码的输出

如何避免您的 IP 地址被禁止?

在执行非常大的提取时,控制爬行率是要记住的最重要的事情。在很短的时间内用多个请求轰炸服务器很可能会导致您的 IP 地址被列入黑名单。为了避免这种情况,我们可以简单地在很短的随机突发时间内进行爬行。换句话说,我们在抓取周期之间添加了暂停或少量中断,这有助于我们看起来像真正的人类,因为与尝试访问网站的人类相比,网站可以轻松识别抓取工具,因为它拥有的速度。这有助于避免不必要的流量和网站服务器过载。双赢!

现在,我们如何控制爬行率?这很简单。通过分别使用Python模块'random' 和 'time' 中的两个函数randint()sleep()



蟒蛇3

from random import randint
from time import sleep 
  
print(randint(1,10))
输出
1

对于循环的每次迭代, randint()函数将在给定的上限和下限之间选择一个随机整数,在这种情况下,分别为 10 和 1。将randint()函数与sleep()函数结合使用将有助于在程序的爬行速度中添加短暂和随机的中断。 sleep()函数基本上会在给定的秒数内停止程序的执行。在此,秒的数量将随机地通过使用randint()函数送入睡眠函数。使用下面给出的代码作为参考。

蟒蛇3

from time import *
from random import randint
  
for i in range(0,3):
  # selects random integer in given range
  x = randint(2,5)
  print(x)
  sleep(x)
  print(f'I waited {x} seconds')
输出
5
I waited 5 seconds
4
I waited 4 seconds
5
I waited 5 seconds

为了让你清楚地了解这个函数的实际作用,请参考下面给出的代码。

蟒蛇3

import requests
from bs4 import BeautifulSoup as bs
from random import randint
from time import sleep
  
URL = 'https://www.geeksforgeeks.org/page/'
  
for page in range(1,10): 
      # pls note that the total number of
    # pages in the website is more than 5000 so i'm only taking the
    # first 10 as this is just an example
  
    req = requests.get(URL + str(page) + '/')
    soup = bs(req.text, 'html.parser')
  
    titles = soup.find_all('div',attrs={'class','head'})
  
    for i in range(4,19):
        if page>1:
            print(f"{(i-3)+page*15}" + titles[i].text)
        else:
            print(f"{i-3}" + titles[i].text)
  
    sleep(randint(2,10))

输出:

程序已暂停执行,正在等待恢复

上面代码的输出