项目简介
一个为Python设计的超快速、自适应的网页抓取工具,能够自动适应网站变化,显著提高网页抓取性能.
处理因网站更改而导致的网络抓取工具失败的情况?
Scrapling 是一个高性能、智能的 Python 网页抓取库,可以自动适应网站变化,同时显着优于流行的替代方案。无论您是初学者还是专家,Scrapling 都提供强大的功能,同时保持简单性。
from scrapling import Adaptor
# Scrape data that survives website changes
page = Adaptor(html, auto_match=True)
products = page.css('.product', auto_save=True)
# Later, even if selectors change:
products = page.css('.product', auto_match=True) # Still finds them!
主要特征
自适应抓取
🔄智能元素跟踪:使用智能相似系统和集成存储,在网站结构更改后定位先前识别的元素。
🎯灵活查询:使用 CSS 选择器、XPath、文本搜索或正则表达式 - 按照您想要的方式链接它们!
🔍查找相似元素:自动定位与页面上您想要的元素相似的元素(例如:其他产品,例如您在页面上找到的产品)。
🧠智能内容抓取:使用其强大的功能,无需特定选择器即可从多个网站提取数据。
表现
🚀快如闪电:从头开始构建时就考虑到了性能,其性能优于最流行的 Python 抓取库(在我们的测试中,其性能比 BeautifulSoup 高出 237 倍)。
🔋内存效率:优化数据结构以最小化内存占用。
⚡快速 JSON 序列化:JSON 序列化速度比标准 json 库快 10 倍,并且具有更多选项。
开发经验
🛠️强大的导航 API :轻松地在各个方向遍历 DOM 树并获取您想要的信息(父元素、祖先元素、兄弟元素、子元素、下一个/上一个元素等)。
🧬富文本处理:所有字符串都有内置的正则表达式匹配、清理等方法。所有元素的属性都是只读字典,比带有添加方法的标准字典更快。
📝自动选择器生成:为任何元素创建强大的 CSS/XPath 选择器。
🔌 Scrapy 兼容 API :Scrapy 用户熟悉的方法和类似的伪元素。
📘类型提示:完整的类型覆盖,以获得更好的 IDE 支持和更少的错误。
入门
让我们通过一个基本示例来演示 Scrapling 的一小部分核心功能:
import requests
from scrapling import Adaptor
# Fetch a web page
url = 'https://quotes.toscrape.com/'
response = requests.get(url)
# Create an Adaptor instance
page = Adaptor(response.text, url=url)
# Get all strings in the full page
page.get_all_text(ignore_tags=('script', 'style'))
# Get all quotes, any of these methods will return a list of strings (TextHandlers)
quotes = page.css('.quote .text::text') # CSS selector
quotes = page.xpath('//span[@class="text"]/text()') # XPath
quotes = page.css('.quote').css('.text::text') # Chained selectors
quotes = [element.text for element in page.css('.quote').css('.text')] # Slower than bulk query above
# Get the first quote element
quote = page.css('.quote').first # or [0] or .get()
# Working with elements
quote.html_content # Inner HTML
quote.prettify() # Prettified version of Inner HTML
quote.attrib # Element attributes
quote.path # DOM path to element (List)
为了简单起见,只要您链接返回元素(称为Adaptor
对象)或适配器列表(称为Adaptors
对象)的方法,所有方法都可以彼此链接在一起
安装
开始清理是一件轻而易举的事情 - 我们只需要至少 Python 3.7 才能工作,其余的要求会随软件包自动安装。
# Using pip
pip install scrapling
# Or the latest from GitHub
pip install git+https://github.com/D4Vinci/Scrapling.git@master
高级功能
智能导航
> quote.tag
'div'
> quote.parent
<data='<div class="col-md-8"> <div class="quote...' parent='<div class="row"> <div class="col-md-8">...'>
> quote.parent.tag
'div'
> quote.children
[<data='<span class="text" itemprop="text">“The...' parent='<div class="quote" itemscope itemtype="h...'>,
<data='<span>by <small class="author" itemprop=...' parent='<div class="quote" itemscope itemtype="h...'>,
<data='<div class="tags"> Tags: <meta class="ke...' parent='<div class="quote" itemscope itemtype="h...'>]
> quote.siblings
[<data='<div class="quote" itemscope itemtype="h...' parent='<div class="col-md-8"> <div class="quote...'>,
<data='<div class="quote" itemscope itemtype="h...' parent='<div class="col-md-8"> <div class="quote...'>,
<data='<div class="quote" itemscope itemtype="h...' parent='<div class="col-md-8"> <div class="quote...'>,
...]
# gets the next element, the same logic applies to `quote.previous` > quote.next
<data='<div class="quote" itemscope itemtype="h...' parent='<div class="col-md-8"> <div class="quote...'>
".author::text") > quote.children.css(
['Albert Einstein']
'quote') > quote.has_class(
True
# Generate new selectors for any element
> quote.css_selector
'body > div > div:nth-of-type(2) > div > div'
# Test these selectors on your favorite browser or reuse them again in the library in other methods!
> quote.xpath_selector
'//body/div/div[2]/div/div'
如果您的情况需要的不仅仅是元素的父级,您可以迭代任何元素的整个祖先树,如下所示
for ancestor in quote.iterancestors():
# do something with it...
您可以搜索满足函数的元素的特定祖先,您所需要做的就是传递一个以Adaptor
对象作为参数的函数,如果条件满足则返回True
,否则返回False
,如下所示:
lambda ancestor: ancestor.has_class('row')) quote.find_ancestor(
<data='<div class="row"> <div class="col-md-8">...' parent='<div class="container"> <div class="row...'>
基于内容的选择和查找相似元素
您可以通过多种方式根据文本内容选择元素,这是另一个网站上的完整示例:
'https://books.toscrape.com/index.html') response = requests.get(
page = Adaptor(response.text, url=response.url)
'Tipping the Velvet') # Find the first element that its text fully matches this text page.find_by_text(
<data='<a href="catalogue/tipping-the-velvet_99...' parent='<h3><a href="catalogue/tipping-the-velve...'>
'Tipping the Velvet', first_match=False) # Get all matches if there are more page.find_by_text(
[<data='<a href="catalogue/tipping-the-velvet_99...' parent='<h3><a href="catalogue/tipping-the-velve...'>]
r'£[\d\.]+') # Get the first element that its text content matches my price regex page.find_by_regex(
<data='<p class="price_color">£51.77</p>' parent='<div class="product_price"> <p class="pr...'>
r'£[\d\.]+', first_match=False) # Get all elements that matches my price regex page.find_by_regex(
[<data='<p class="price_color">£51.77</p>' parent='<div class="product_price"> <p class="pr...'>,
<data='<p class="price_color">£53.74</p>' parent='<div class="product_price"> <p class="pr...'>,
<data='<p class="price_color">£50.10</p>' parent='<div class="product_price"> <p class="pr...'>,
<data='<p class="price_color">£47.82</p>' parent='<div class="product_price"> <p class="pr...'>,
...]
查找位置和属性与当前元素相似的所有元素
# For this case, ignore the 'title' attribute while matching
'Tipping the Velvet').find_similar(ignore_attributes=['title']) > page.find_by_text(
[<data='<a href="catalogue/a-light-in-the-attic_...' parent='<h3><a href="catalogue/a-light-in-the-at...'>,
<data='<a href="catalogue/soumission_998/index....' parent='<h3><a href="catalogue/soumission_998/in...'>,
<data='<a href="catalogue/sharp-objects_997/ind...' parent='<h3><a href="catalogue/sharp-objects_997...'>,
...]
# You will notice that the number of elements is 19 not 20 because the current element is not included.
'Tipping the Velvet').find_similar(ignore_attributes=['title'])) > len(page.find_by_text(
19
# Get the `href` attribute from all similar elements
'href'] for element in page.find_by_text('Tipping the Velvet').find_similar(ignore_attributes=['title'])] > [element.attrib[
['catalogue/a-light-in-the-attic_1000/index.html',
'catalogue/soumission_998/index.html',
'catalogue/sharp-objects_997/index.html',
...]
为了增加一点复杂性,假设我们出于某种原因想要使用该元素作为起点来获取所有书籍的数据
for product in page.find_by_text('Tipping the Velvet').parent.parent.find_similar():
print({
"name": product.css('h3 a::text')[0],
"price": product.css('.price_color')[0].re_first(r'[\d\.]+'),
"stock": product.css('.availability::text')[-1].clean()
})
{'name': 'A Light in the ...', 'price': '51.77', 'stock': 'In stock'}
{'name': 'Soumission', 'price': '50.10', 'stock': 'In stock'}
{'name': 'Sharp Objects', 'price': '47.82', 'stock': 'In stock'}
...
项目链接
https://github.com/D4Vinci/Scrapling
扫码加入技术交流群,备注「开发语言-城市-昵称」
合作请注明
关注「GitHubStore」公众号