首先 – 什么是站点地图?站点地图是网络文件,列出网络对象的位置,例如网络爬虫的产品页面、文章等。它主要用于告诉搜索引擎索引什么,尽管在网络抓取中我们可以使用它们来发现要抓取的目标。
在本教程中,我们将了解如何使用 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 中,我们可以通过XPath或CSS 选择器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 或axios
Javascript 中)和 XML 解析器(lxml
或cheerio
)。
站点地图是发现新的抓取目标并快速了解网站结构的好方法。不过,并非每个网站都支持它们,值得注意的是站点地图上的数据可能比网站本身的数据更旧。