{"record":{"id":"bc5c5be11ec1dacb","repo":"iawia002/lux","slug":"invalid-url-for-yinyuetai","errorCode":null,"errorMessage":"invalid url for yinyuetai","messagePattern":"invalid url for yinyuetai","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"extractors/yinyuetai/yinyuetai.go","lineNumber":44,"sourceCode":"}\n\ntype extractor struct{}\n\n// New returns a yinyuetai extractor.\nfunc New() extractors.Extractor {\n\treturn &extractor{}\n}\n\n// Extract is the main function to extract the data.\nfunc (e *extractor) Extract(url string, option extractors.Options) ([]*extractors.Data, error) {\n\tvid := utils.MatchOneOf(\n\t\turl,\n\t\t`https?://v.yinyuetai.com/video/(\\d+)(?:\\?vid=\\d+)?`,\n\t\t`https?://v.yinyuetai.com/video/h5/(\\d+)(?:\\?vid=\\d+)?`,\n\t\t`https?://m2.yinyuetai.com/video.html\\?id=(\\d+)`,\n\t)\n\tif vid == nil || len(vid) < 2 {\n\t\treturn nil, errors.New(\"invalid url for yinyuetai\")\n\t}\n\tparams := fmt.Sprintf(\"videoId=%s\", vid[1])\n\t// generate api url\n\tapiURL := genAPI(actionGetMvInfo, params)\n\tvar err error\n\thtml, err := request.Get(apiURL, url, nil)\n\tif err != nil {\n\t\treturn nil, errors.WithStack(err)\n\t}\n\t// parse yinyuetai data\n\tdata := yinyuetaiMvData{}\n\tif err = json.Unmarshal([]byte(html), &data); err != nil {\n\t\treturn nil, errors.WithStack(extractors.ErrURLParseFailed)\n\t}\n\t// handle api error\n\tif data.Error {\n\t\treturn nil, errors.New(data.Message)\n\t}","sourceCodeStart":26,"sourceCodeEnd":62,"githubUrl":"https://github.com/iawia002/lux/blob/dd00f6d258d80b6684a0b9402d7124e5c18ef42f/extractors/yinyuetai/yinyuetai.go#L26-L62","documentation":"The YinYueTai extractor only accepts three URL shapes: v.yinyuetai.com/video/<id>, v.yinyuetai.com/video/h5/<id>, and m2.yinyuetai.com/video.html?id=<id>. If none of the three regexes matches, the video id cannot be extracted and this error is returned before any network call is made.","triggerScenarios":"Passing a www.yinyuetai.com host, a fan/stage page, a URL with the id in an unexpected query param, or any post-rebrand domain layout that no longer matches the three patterns.","commonSituations":"YinYueTai rebranded/reorganized its site so canonical video permalinks changed; users paste search-result or playlist URLs; trailing fragments or encoded characters break the match.","solutions":["Rewrite the URL to the canonical form https://v.yinyuetai.com/video/<id> before extracting","Confirm the URL opens a video page in a browser","If the domain layout changed permanently, add the new pattern to the MatchOneOf call in extractors/yinyuetai/yinyuetai.go","Validate the URL against the three patterns on the caller side first"],"exampleFix":"// before\n_, err := yinyuetai.Extract(\"https://www.yinyuetai.com/video/2515284\", opts) // wrong host -> error\n\n// after\n_, err := yinyuetai.Extract(\"https://v.yinyuetai.com/video/2515284\", opts) // matches first pattern","handlingStrategy":"validation","validationCode":"var yinyuetaiRe = regexp.MustCompile(`^https?://(v\\.yinyuetai\\.com/video/(h5/)?\\d+(\\?vid=\\d+)?$|https?://m2\\.yinyuetai\\.com/video\\.html\\?id=\\d+)`)\n\nfunc isYinyuetaiVideoURL(raw string) bool {\n    return yinyuetaiRe.MatchString(raw)\n}","typeGuard":null,"tryCatchPattern":"if !isYinyuetaiVideoURL(url) {\n    // rewrite to canonical https://v.yinyuetai.com/video/<id> or reject\n}\n_, err := yinyuetai.Extract(url, opts)","preventionTips":["Normalize every yinyuetai URL to the v.yinyuetai.com/video/<id> form before extracting","Keep the accepted-pattern list in sync with the extractor when adding hosts","Reject www.* and non-video page URLs early in batch pipelines"],"tags":["yinyuetai","url-validation","regex"],"backgroundTag":null,"analyzedSha":"dd00f6d258d80b6684a0b9402d7124e5c18ef42f","analyzedAt":"2026-08-15T16:57:31.080Z","schemaVersion":2},"datasetVersion":"2026-08-15T22:17:37.221Z"}