这是我在这里的第一个问题,我正在学习如何自己编码,所以请耐心等待。
我正在制作最终的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的每个课程,并获取名称,说明,提供商,页面网址和图片网址。
对于为什么可能出现问题的任何想法?
答案 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)