in

如何爬取网站地图以发现爬取目标

如何爬取网站地图

首先 – 什么是站点地图?站点地图是网络文件,列出网络对象的位置,例如网络爬虫的产品页面、文章等。它主要用于告诉搜索引擎索引什么,尽管在网络抓取中我们可以使用它们来发现要抓取的目标。

在本教程中,我们将了解如何使用 Python 和 Javascript 发现站点地图文件并抓取它们。在本指南中,我们将介绍:

  • 查找站点地图位置。
  • 如何理解和导航站点地图。
  • 如何使用 Python 和 Javascript 中的 XML 解析工具解析站点地图文件。

为此,我们将使用 Python 或 Javascript 以及一些社区包和一些真实示例。让我们开始吧!

为什么要爬取站点地图?

抓取站点地图是一种发现网站上列出的目标的有效方法,无论是产品页面、博客文章还是任何其他网络对象。站点地图通常是 XML 文档,按类别以 50 000 个为一批列出 URL。站点地图通常采用 gzip 压缩,使其成为一种发现页面 URL 的低带宽方式。

因此,我们可以抓取站点地图文件,而不是抓取可能包含数千个 HTML 页面的网站搜索或目录,并在一小部分时间和带宽成本下获得相同的结果。此外,由于站点地图是网络抓取工具创建的,因此被阻止的可能性要低得多。

在哪里可以找到站点地图?

站点地图通常位于网站/sitemap.xml文件的根目录下。但是,没有明确的标准位置,因此找到站点地图位置的另一种方法是浏览/robots.txt为网络爬虫提供说明的标准文件。

现在我们以爬取API ScrapFly的网站为例

Sitemap: https://scrapfly.io/sitemap.xml

许多编程语言都内置了 robot.txt 解析器,或者它就像检索页面内容并找到带有Sitemap:前缀的行一样简单:

# built-in sitemap parser:
from urllib.robotparser import RobotFileParser

rp = RobotFileParser('http://scrapfly.io/robots.txt')
rp.read()
print(rp.site_maps())
['https://www.jingzhengli.com/sitemap-posts.xml', 'https://scrapfly.io/sitemap.xml']
# or httpx
import httpx
response = httpx.get('https://scrapfly.io/robots.txt')
for line in response.text.splitlines():
    if line.strip().startswith('Sitemap:'):
        print(line.split('Sitemap:')[1].strip())

抓取站点地图

站点地图是具有特定、简单结构的 XML 文档。例如:

<?xml version="1.0" encoding="UTF-8"?><?xml-stylesheet type="text/xsl" href="//jingzhengli.com/sitemap.xsl"?>
<urlset xmlns="http://www.sitemaps.org/schemas/sitemap/0.9" xmlns:image="http://www.google.com/schemas/sitemap-image/1.1">
  <url>
    <loc>https://www.jingzhengli.com/web-scraping-with-python/</loc>
    <lastmod>2023-04-04T06:20:35.000Z</lastmod>
    <image:image>
      <image:loc>https://www.jingzhengli.com/content/images/web-scraping-with-python_banner.svg</image:loc>
      <image:caption>web-scraping-with-python_banner.svg</image:caption>
    </image:image>
  </url>
</urlset>

当谈到网络抓取时,我们最感兴趣的是<urlset>每个值都<url>包含位置和一些可选的元数据,例如:

  • <loc>– 资源的 URL 位置。
  • <lastmod>– 上次修改资源的时间戳。
  • <changefreq>– 资源预期更改的频率(总是、每小时、每天、每周、每月、每年或从不)。
  • <priority>– 资源索引重要性(0.0 – 1.0)。这主要用于搜索引擎。
  • <image:image>– 与资源关联的图像列表。
  • <image:loc>– 图片的 URL(例如主要产品图片或文章特色图片)。
  • <image:caption>– 图像的简短描述。
  • <image:geo_location>– 图片的地理位置。
  • <image:title>– 图片的标题。
  • <image:license>– 图像许可证的 URL。
  • <video:video>– 类似于<image:loc>但用于视频。

要解析站点地图,我们需要一个 XML 解析器,我们可以使用它来查找所有<url>元素并提取值。

在 Python 中,我们可以通过XPathCSS 选择器lxml使用或parsel封装来解析 XML 文档。

from parsel import Selector
import httpx

response = httpx.get("https://www.jingzhengli.com/sitemap-posts.xml")
selector = Selector(response.text)
for url in selector.xpath('//url'):
    location = url.xpath('loc/text()').get()
    modified = url.xpath('lastmod/text()').get()
    print(location, modified)
    ["https://www.jingzhengli.com/how-to-scrape-nordstrom/", "2023-04-06T13:35:47.000Z"]

在 javascript(以及 NodeJS 和 TypeScript)中,最流行的 XML 解析库是可以与CSS 选择器cheerio一起使用的:

// npm install axios cheerio
import axios from 'axios';
import * as cheerio from 'cheerio';


const response = await axios.get('https://www.jingzhengli.com/sitemap-posts.xml');
const $ = cheerio.load(response.data, { xmlMode: true });
$('url').each((_, urlElem) => {
    const location = $(urlElem).find('loc').text();
    const modified = $(urlElem).find('lastmod').text();
    console.log(location, modified);
});

 

对于较大的网站,50 000 个 URL 的站点地图限制通常是不够的,因此站点地图中心包含多个站点地图文件。为了抓取这个,我们需要一些递归。

例如,让我们看一下StockX站点地图中心。首先,我们可以看到 robots.txt 文件包含以下行:

Sitemap: https://stockx.com/sitemap/sitemap-index.xml

此索引文件包含多个站点地图:

<sitemapindex xmlns="http://www.sitemaps.org/schemas/sitemap/0.9">
<sitemap>
  <loc>https://stockx.com/sitemap/sitemap-0.xml</loc>
</sitemap>
<sitemap>
  <loc>https://stockx.com/sitemap/sitemap-1.xml</loc>
</sitemap>
<sitemap>
  <loc>https://stockx.com/sitemap/sitemap-2.xml</loc>
</sitemap>
<sitemap>
  <loc>https://stockx.com/sitemap/sitemap-3.xml</loc>
</sitemap>
<sitemap>
  <loc>https://stockx.com/sitemap/sitemap-4.xml</loc>
</sitemap>
<sitemap>
  <loc>https://stockx.com/sitemap/sitemap-5.xml</loc>
</sitemap>
</sitemapindex>

有时,站点地图中心会按类别和位置拆分站点地图,这可以帮助我们定位特定类型的页面。尽管要抓取集线器,我们所要做的就是解析索引文件并抓取每个站点地图文件:

Python

from parsel import Selector
import httpx

response = httpx.get("https://stockx.com/sitemap/sitemap-index.xml")
selector = Selector(response.text)
for sitemap_url in selector.xpath("//sitemap/loc/text()").getall():
  response = httpx.get(sitemap_url)
  selector = Selector(response.text)
  for url in selector.xpath('//url'):
      location = url.xpath('loc/text()').get()
      change_frequency = url.xpath('changefreq/text()').get()  # it's an alternative field to modification date
      print(location, change_frequency)

Javascript

import axios from 'axios';
import * as cheerio from 'cheerio';


const response = await axios.get('https://stockx.com/sitemap/sitemap-index.xml');
const sitemapIndex = cheerio.load(response.data, { xmlMode: true });
sitemapIndex('loc').each(async (_, urlElem) => {
    const sitemapUrl = sitemapIndex(urlElem).text();
    const response = await axios.get(sitemapUrl);
    const $ = cheerio.load(response.data, { xmlMode: true });
    $('url').each((_, urlElem) => {
        const location = $(urlElem).find('loc').text();
        const changefreq = $(urlElem).find('changefrq').text();
        console.log(location, changefreq);
    });
});

站点地图抓取摘要

在这个简短的介绍中,我们了解了最流行的发现抓取目标的方法——站点地图系统。为了抓取它,我们使用了 HTTP 客户端(httpx在 Python 或axiosJavascript 中)和 XML 解析器(lxmlcheerio)。

站点地图是发现新的抓取目标并快速了解网站结构的好方法。不过,并非每个网站都支持它们,值得注意的是站点地图上的数据可能比网站本身的数据更旧。

Written by 河小马

河小马是一位杰出的数字营销行业领袖,广告中国论坛的重要成员,其专业技能涵盖了PPC广告、域名停放、网站开发、联盟营销以及跨境电商咨询等多个领域。作为一位资深程序开发者,他不仅具备强大的技术能力,而且在出海网络营销方面拥有超过13年的经验。