实时抓取网页数据(如何使用Scrapy提取数据的最佳方法是使用shellScrapyshell尝试选择器)

优采云 发布时间: 2021-11-25 15:14

  实时抓取网页数据(如何使用Scrapy提取数据的最佳方法是使用shellScrapyshell尝试选择器)

  提取数据

  学习如何使用 Scrapy 提取数据的最好方法是尝试使用 shellScrapy shell 的选择器。跑:

  scrapy shell 'http://quotes.toscrape.com/page/1/'

  注意

  从命令行运行 Scrapy shell 时,请记住始终将 URL 括在引号中,否则收录参数(即 & 字符)的 URL 将不起作用。

  在 Windows 上,使用双引号:

  scrapy shell "http://quotes.toscrape.com/page/1/"

  你会看到类似的东西:

  [ ... Scrapy log here ... ] 2016-09-19 12:09:27 [scrapy.core.engine] DEBUG: Crawled (200) (referer: None) [s] Available Scrapy objects: [s] scrapy scrapy module (contains scrapy.Request, scrapy.Selector, etc) [s] crawler [s] item {} [s] request [s] response [s] settings [s] spider [s] Useful shortcuts: [s] shelp() Shell help (print this help) [s] fetch(req_or_url) Fetch request (or URL) and update local objects [s] view(response) View response in a browser >>>

  使用 shell,您可以尝试使用 CSS 和响应对象来选择元素:

  >>> response.css('title') []

  运行 response.css('title') 的结果是一个类似列表的对象 SelectorList,它表示一个收录 XML/HTML 元素的 Selector 对象列表,并允许您运行进一步的查询以优化选择或提取数据。

  要从上面的标题中提取文本,您可以执行以下操作:

  >>> response.css('title::text').extract() ['Quotes to Scrape']

  这里有两点需要注意:一是我们在CSS查询中添加了::text,这意味着我们只想直接在元素内选择文本元素。如果我们不指定::text,我们将获得完整的标题元素,包括它的标签:

  >>> response.css('title').extract() ['Quotes to Scrape']

  另一件事是调用 .extract() 的结果是一个列表,因为我们正在处理 SelectorList 的一个实例。当你知道你只想要第一个结果时,就像在这种情况下一样,你可以这样做:

  >>> response.css('title::text').extract_first() 'Quotes to Scrape'

  作为替代方案,您可以编写:

  >>> response.css('title::text')[0].extract() 'Quotes to Scrape'

  但是,当它找不到任何与选择匹配的元素时,使用 .extract_first() 来避免 IndexError 并返回 None。

  这里有一个教训:对于大多数爬虫代码,你希望它在页面上什么都找不到的情况下能够适应错误,所以即使某些部分无法删除,你至少可以得到一些数据。

  除了extract()和extract_first()方法之外,还可以使用re()方法用正则表达式进行提取:

  >>> response.css('title::text').re(r'Quotes.*') ['Quotes to Scrape'] >>> response.css('title::text').re(r'Qw+') ['Quotes'] >>> response.css('title::text').re(r'(w+) to (w+)') ['Quotes', 'Scrape']

  为了找到正确的 CSS 选择器,您可能会发现在 Web 浏览器中使用 shell 打开响应页面视图(响应)非常有用。您可以使用浏览器开发工具或扩展程序(例如 Firebug)(请参阅有关使用 Firebug 进行爬网和使用 Firefox 进行爬网的部分)。

  Selector Gadget 也是一个很好的工具,可以快速找到可视化选择元素的 CSS 选择器,可以在很多浏览器中使用。

  XPath:简介

  除了 CSS,Scrapy 选择器还支持使用 XPath 表达式:

  >>> response.xpath('//title') [] >>> response.xpath('//title/text()').extract_first() 'Quotes to Scrape'

  XPath 表达式非常强大,是 Scrapy 选择器的基础。事实上,CSS 选择器在幕后转换为 XPath。如果仔细阅读 shell 中选择器对象的文本表示,您可以看到它。

  尽管它可能不如 CSS 选择器流行,但 XPath 表达式提供了更*敏*感*词*,因为除了导航结构之外,它还可以查看内容。使用 XPath,您可以选择以下内容: 选择收录文本“下一页”的链接。这使得 XPath 非常适合抓取任务,我们鼓励您学习 XPath,即使您已经知道如何构建 CSS 选择器,它也会使抓取更容易。

  我们不会在此处介绍 XPath 的大部分内容,但您可以在此处阅读有关在 Scrapy 选择器中使用 XPath 的更多信息。想进一步了解XPath,我们推荐本教程通过实例学习XPath,本教程将学习“How to Think in XPath”。

  提取引号和作者

  现在您已经了解了一些关于选择和提取的知识,让我们通过编写代码从网页中提取引号来完成我们的蜘蛛。

  中的每个引用都由一个 HTML 元素表示,如下所示:

   “The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.” by Albert Einstein (about) Tags: change deep-thoughts thinking world

  让我们打开scrapy shell,玩一下,学习如何提取我们想要的数据:

  $ scrapy shell 'http://quotes.toscrape.com'

  我们得到一个引用 HTML 元素的选择器列表:

  >>> response.css("div.quote")

  上述查询返回的每个选择器都允许我们对其子元素运行进一步的查询。让我们将第一个选择器分配给一个变量,以便我们可以直接在特定引号上运行 CSS 选择器:

  >>> quote = response.css("div.quote")[0]

  现在,让我们使用刚刚创建的对象从引用中提取标题、作者和标签:

  >>> title = quote.css("span.text::text").extract_first() >>> title '“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”' >>> author = quote.css("small.author::text").extract_first() >>> author 'Albert Einstein'

  鉴于标签是一个字符串列表,我们可以使用 .extract() 方法来获取所有这些:

  >>> tags = quote.css("div.tags a.tag::text").extract() >>> tags ['change', 'deep-thoughts', 'thinking', 'world']

  在弄清楚如何提取每一位之后,我们现在可以遍历所有引用的元素并将它们一起放入 Python 字典中:

  >>> for quote in response.css("div.quote"): ... text = quote.css("span.text::text").extract_first() ... author = quote.css("small.author::text").extract_first() ... tags = quote.css("div.tags a.tag::text").extract() ... print(dict(text=text, author=author, tags=tags)) {'tags': ['change', 'deep-thoughts', 'thinking', 'world'], 'author': 'Albert Einstein', 'text': '“The world as we have created it is a process of our thinking. It cannot be changed without changing our thinking.”'} {'tags': ['abilities', 'choices'], 'author': 'J.K. Rowling', 'text': '“It is our choices, Harry, that show what we truly are, far more than our abilities.”'} ... a few more of these, omitted for brevity >>>

  在我们的蜘蛛中提取数据

  让我们回到我们的蜘蛛。到目前为止,它还没有特别提取任何数据,它只是将整个 HTML 页面保存到本地文件中。让我们将上述提取逻辑集成到我们的蜘蛛中。

  Scrapy Spider 通常会生成许多字典,其中收录从页面中提取的数据。为此,我们在回调中使用了Python关键字yield,如下图:

  import scrapy class QuotesSpider(scrapy.Spider): name = "quotes" start_urls = [ 'http://quotes.toscrape.com/page/1/', 'http://quotes.toscrape.com/page/2/', ] def parse(self, response): for quote in response.css('div.quote'): yield { 'text': quote.css('span.text::text').extract_first(), 'author': quote.css('small.author::text').extract_first(), 'tags': quote.css('div.tags a.tag::text').extract(), }

  如果你运行这个蜘蛛,它会输出提取的数据和日志:

  2016-09-19 18:57:19 [scrapy.core.scraper] DEBUG: Scraped from {'tags': ['life', 'love'], 'author': 'André Gide', 'text': '“It is better to be hated for what you are than to be loved for what you are not.”'} 2016-09-19 18:57:19 [scrapy.core.scraper] DEBUG: Scraped from {'tags': ['edison', 'failure', 'inspirational', 'paraphrased'], 'author': 'Thomas A. Edison', 'text': "“I have not failed. I've just found 10,000 ways that won't work.”"}

  存储已删除的数据

  存储已删除数据的最简单方法是使用提要导出,使用以下命令:

  scrapy crawl quotes -o quotes.json

  这将生成一个收录所有已删除项目的quotes.json 文件,以JSON 序列化。

  由于历史原因,Scrapy 将附加到给定文件而不是覆盖其内容。如果您在第二次之前运行此命令两次而没有删除该文件,您最终会得到一个损坏的 JSON 文件。

  您还可以使用其他格式,例如 JSON Lines:

  scrapy crawl quotes -o quotes.jl

  JSON 行格式很有用,因为它经过简化,您可以轻松地向其追加新记录。当您运行它两次时,它没有相同的 JSON 问题。另外,由于每条记录都是单独的一行,所以你可以处理大文件而不用把所有东西都放在内存中,一些工具比如JQ可以帮助你在命令行中做到这一点。

  在小型项目(例如本教程中的项目)中,这应该足够了。但是,如果要对已删除的项执行更复杂的操作,则可以编写项目管道。在您创建项目时,项目管道的占位符文件已经为您设置了 tutorial/pipelines.py。如果您只想存储已删除的项目,则无需实现任何项目管道。

  以下链接

  假设您不需要从前两页抓取内容,但是您需要 网站 的所有页面的引号。

  现在您知道如何从页面中提取数据,让我们看看如何从中获取链接。

0 个评论

要回复文章请先登录注册


官方客服QQ群

微信人工客服

QQ人工客服


线