Scrapy spider输出empy csv文件

时间:2018-01-02 17:05:41

标签: python csv web-scraping scrapy scrapy-spider

这是我在这里的第一个问题,我正在学习如何自己编码,所以请耐心等待。

我正在制作最终的CS50项目,我试图建立一个网站,汇集来自edx.org和其他开放式在线课程网站的在线西班牙语课程。我使用scrapy框架来废弃edx.org上的西班牙语课程的过滤结果......这是我的第一个scrapy蜘蛛,我试图在每个课程链接中获取它然后得到它#s; s名称(在我获得正确的代码之后,也获得描述,课程网址和更多内容)。

from scrapy.item import Field, Item
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractor import LinkExtractor
from scrapy.loader import ItemLoader

class Course_item(Item):
    name = Field()
    #description = Field()
    #img_url = Field()


class Course_spider(CrawlSpider):
    name = 'CourseSpider'
    allowed_domains = ['https://www.edx.org/']
    start_urls = ['https://www.edx.org/course/?language=Spanish']

    rules = (Rule(LinkExtractor(allow=r'/course'), callback='parse_item', follow='True'),)

    def parse_item(self, response):
        item = ItemLoader(Course_item, response)
        item.add_xpath('name', '//*[@id="course-intro-heading"]/text()')

        yield item.load_item()

当我使用" scrapy runspider edxSpider.py -o edx.csv -t csv"我得到一个空的csv文件,我也认为没有进入正确的西班牙语课程结果。

基本上我想参加此链接edx Spanish courses的每个课程,并获取名称,说明,提供商,页面网址和图片网址。

对于为什么可能出现问题的任何想法?

3 个答案:

答案 0 :(得分:2)

您无法通过简单的请求获取edx内容,它会使用javascript呈现动态获取课程元素,因此CrawlSpider无法解决此案例,因为您需要在响应主体内部找到特定元素,以生成一个新的请求,以获得所需的内容。

真实的请求(获取课程的网址)是this one,但您需要从之前的响应主体生成它(尽管您可以访问它并获得正确的数据)。

因此,要生成实际请求,您需要script标记内的数据:

from scrapy import Spider
import re
import json

class Course_spider(Spider):
    name = 'CourseSpider'
    allowed_domains = ['edx.org']
    start_urls = ['https://www.edx.org/course/?language=Spanish']

    def parse(self, response):
        script_text = response.xpath('//script[contains(text(), "Drupal.settings")]').extract_first()
        parseable_json_data = re.search(r'Drupal.settings, ({.+})', script_text).group(1)
        json_data = json.loads(parseable_json_data)
        ...

现在,您在json_data拥有所需内容,只需要创建字符串URL。

答案 1 :(得分:1)

此页面使用JavaScript从服务器获取数据并添加到页面。

它使用像

这样的网址
https://www.edx.org/api/catalog/v2/courses/course-v1:IDBx+IDB33x+3T2017

最后一部分是您可以在HTML中找到的课程编号

<main id="course-info-page" data-course-id="course-v1:IDBx+IDB33x+3T2017">

代码

from scrapy.http import Request
from scrapy.item import Field, Item
from scrapy.spiders import CrawlSpider, Rule
from scrapy.linkextractor import LinkExtractor
from scrapy.loader import ItemLoader
import json

class Course_spider(CrawlSpider):

    name = 'CourseSpider'
    allowed_domains = ['www.edx.org']
    start_urls = ['https://www.edx.org/course/?language=Spanish']

    rules = (Rule(LinkExtractor(allow=r'/course'), callback='parse_item', follow='True'),)

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

        course_id = response.xpath('//*[@id="course-info-page"]/@data-course-id').extract_first()

        if course_id:
            url = 'https://www.edx.org/api/catalog/v2/courses/' + course_id
            yield Request(url, callback=self.parse_json)

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

        item = json.loads(response.body)

        return item

from scrapy.crawler import CrawlerProcess

c = CrawlerProcess({
    'USER_AGENT': 'Mozilla/5.0',
    'FEED_FORMAT': 'csv',     # csv, json, xml
    'FEED_URI': 'output.csv', #     
})
c.crawl(Course_spider)
c.start()

答案 2 :(得分:0)

user_org => fld_id 
            user (usertable.fldid)
            org  (Organization.fld_id)