【问题标题】:How to scrape webpage with scrapy framework?如何使用 scrapy 框架抓取网页?
【发布时间】:2017-12-18 14:42:22
【问题描述】:

我是网页抓取的新手。我已经开始学习scrapy框架了。

我介绍了 scrapy 的基本教程。现在我正在尝试废弃this 页面。

根据this 教程,要让整个 html 页面包含一个应该编写以下代码:

import scrapy


class ClothesSpider(scrapy.Spider):
    name = "clothes"

    start_urls = [
        'https://www.chumbak.com/women-apparel/GY1/c/',
    ]

    def parse(self, response):
        filename = 'clothes.html'
        with open(filename, 'wb') as f:
            f.write(response.body)

这段代码运行良好。但我没有得到预期的结果。

当我打开 clothes.html 时,html 数据与我从浏览器进行检查时不同。 clothes.html 中缺少很多东西。

我不明白这里出了什么问题。请帮助我向前推进。 任何帮助将不胜感激。

谢谢。

【问题讨论】:

  • 浏览器的检查工具不显示 HTML;它向您展示了当时存在的 DOM。大概页面是由 JavaScript 修改的。如果您使用查看源代码(在 Firefox 或 Chrome 中为 Ctrl+U),您应该会看到与 scrapy 相同的效果。
  • 今天的许多页面都是动态的并且倾向于呈现自己。考虑使用无头浏览器
  • @Thomas,感谢您的帮助。有什么办法可以通过scrapy得到JS修改后的结果?
  • JavaScript 主要从某些 url 读取数据 - 如果您在 Chrome/Firefox 的 DevTools 中找到这些 url(选项卡 Network->XHR),那么您也可以在没有 Selenium 的情况下读取这些数据。
  • 此页面从类似于https://api-cdn.chumbak.com/v1/category/474/products/?count_per_page=24&page=2 的url读取数据(作为JSON)

标签: python web-scraping scrapy


【解决方案1】:

此页面使用 JavaScript 将数据放在页面上。

在 Chrome/Firefox 中使用 DevTool,您可以查看哪些 url 使用 JavaScript 从服务器获取此数据(选项卡网络,过滤 XHR)

然后你也可以尝试获取数据。

代码为带有 JSON 数据的 10 个页面生成 url 并下载它们,保存在单独的文件中,生成完整的图像 url 和 Scrapy 将它们下载到子文件夹 fullScrapy 还保存在output.json 所有关于下载图像的yield 数据中。

#!/usr/bin/env python3

import scrapy
#from scrapy.commands.view import open_in_browser
import json

class MySpider(scrapy.Spider):

    name = 'myspider'

    #allowed_domains = []

    #start_urls = ['https://www.chumbak.com/women-apparel/GY1/c/']

    #start_urls = [
    #    'https://api-cdn.chumbak.com/v1/category/474/products/?count_per_page=24&page=1',
    #    'https://api-cdn.chumbak.com/v1/category/474/products/?count_per_page=24&page=2',
    #    'https://api-cdn.chumbak.com/v1/category/474/products/?count_per_page=24&page=3',
    #]

    def start_requests(self):
        pages = 10
        url_template = 'https://api-cdn.chumbak.com/v1/category/474/products/?count_per_page=24&page={}'

        for page in range(1, pages+1):
            url = url_template.format(page)
            yield scrapy.Request(url)

    def parse(self, response):
        print('url:', response.url)

        #open_in_browser(response)

        # get page number
        page_number = response.url.strip('=')[-1]

        # save JSON in separated file
        filename = 'page-{}.json'.format(page_number)
        with open(filename, 'wb') as f:
           f.write(response.body)

        # convert JSON into Python's dictionary
        data = json.loads(response.text)

        # get urls for images
        for product in data['products']:
            #print('title:', product['title'])
            #print('url:', product['url'])
            #print('image_url:', product['image_url'])

            # create full url to image
            image_url = 'https://media.chumbak.com/media/catalog/product/small_image/260x455' + product['image_url']
            # send it to scrapy and it will download it
            yield {'image_urls': [image_url]}


        # download files
        #for href in response.css('img::attr(href)').extract():
        #   url = response.urljoin(src)
        #   yield {'file_urls': [url]}

        # download images and convert to JPG
        #for src in response.css('img::attr(src)').extract():
        #   url = response.urljoin(src)
        #   yield {'image_urls': [url]}

# --- it runs without project and saves in `output.csv` ---

from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0',

    # save in CSV or JSON
    'FEED_FORMAT': 'json',     # 'cvs', 'json', 'xml'
    'FEED_URI': 'output.json', # 'output.cvs', 'output.json', 'output.xml'

    # download files to `FILES_STORE/full`
    # it needs `yield {'file_urls': [url]}` in `parse()`
    #'ITEM_PIPELINES': {'scrapy.pipelines.files.FilesPipeline': 1},
    #'FILES_STORE': '/path/to/valid/dir',

    # download images and convert to JPG
    # it needs `yield {'image_urls': [url]}` in `parse()`
    #'ITEM_PIPELINES': {'scrapy.pipelines.images.ImagesPipeline': 1},
    #'IMAGES_STORE': '/path/to/valid/dir',
    'ITEM_PIPELINES': {'scrapy.pipelines.images.ImagesPipeline': 1},
    'IMAGES_STORE': '.',
})
c.crawl(MySpider)
c.start()

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-09-15
    • 2023-04-03
    • 2021-08-02
    • 1970-01-01
    • 1970-01-01
    • 2015-04-15
    • 2021-01-13
    相关资源
    最近更新 更多