Python信用卡识别程序优化:循环遍历文件返回错误结果问题
Hey there! Let's dig into why your credit card detection script is spitting out every card issuer instead of just the matching one. From what you described, the core issue is that your loop over the rules file isn't properly checking if the input card number meets the issuer's specific prefix and length requirements—so it's just adding every entry to the result list instead of filtering. Let's fix that with targeted changes.
Problem Breakdown
Common missteps that lead to this issue:
- You’re not validating the card number against the issuer’s specific prefix ranges (e.g., MasterCard’s 55-59 or 2221-2720 prefixes)
- You’re skipping length checks (different issuers have fixed card lengths—MasterCard is always 16 digits, Amex is 15)
- You’re not filtering results, just appending every issuer regardless of a match
Optimized Solution Code
Here’s a revised version of your program that fixes these gaps, including proper file IO, issuer matching, and Luhn validation:
1. Load Issuer Rules from File
First, we’ll parse the rules file correctly to capture prefix ranges and valid card lengths:
def load_issuer_rules(file_path): issuers = [] with open(file_path, 'r') as file: for line in file: line = line.strip() if not line or line.startswith('#'): # Skip blank lines/comments continue # Split line into name, prefix ranges, valid lengths (adjust delimiter if your file uses something else) name, prefixes_str, lengths_str = line.split(':') # Parse prefix ranges (supports single values like "4" or ranges like "55-59") prefix_ranges = [] for p in prefixes_str.split(','): if '-' in p: start, end = p.split('-') prefix_ranges.append((int(start), int(end))) else: prefix_ranges.append((int(p), int(p))) # Parse valid card lengths valid_lengths = [int(l) for l in lengths_str.split(',')] issuers.append({ 'name': name, 'prefixes': prefix_ranges, 'lengths': valid_lengths }) return issuers
2. Luhn Validation Function
The standard check for card number validity:
def validate_luhn(card_number): card_digits = [int(d) for d in str(card_number).strip()] reversed_digits = card_digits[::-1] total = 0 for index, digit in enumerate(reversed_digits): if index % 2 == 1: doubled = digit * 2 total += doubled if doubled <= 9 else doubled - 9 else: total += digit return total % 10 == 0
3. Match Card to Issuer
This function filters only issuers that match the card’s prefix and length:
def find_matching_issuer(card_number, issuers): card_str = str(card_number).strip() matching = [] for issuer in issuers: # First check if card length is valid for this issuer if len(card_str) not in issuer['lengths']: continue # Check all prefix ranges for the issuer for prefix_start, prefix_end in issuer['prefixes']: prefix_length = len(str(prefix_start)) # Make sure card is long enough to check this prefix if len(card_str) >= prefix_length: card_prefix = int(card_str[:prefix_length]) if prefix_start <= card_prefix <= prefix_end: matching.append(issuer['name']) break # No need to check other prefixes for this issuer return matching
4. Main Program
Tie it all together to handle user input and output results:
def main(): try: card_number = input("Enter your credit card number: ").strip() # Load rules (update path to match your file location) issuers = load_issuer_rules('card_issuers.txt') # Get matching issuers and validate Luhn matched_issuers = find_matching_issuer(card_number, issuers) luhn_valid = validate_luhn(card_number) # Print results print("\n--- Credit Card Detection Result ---") if matched_issuers: print(f"Card Issuer: {', '.join(matched_issuers)}") else: print("No matching card issuer found.") print(f"Luhn Check: {'Valid' if luhn_valid else 'Invalid'}") except FileNotFoundError: print("Error: Could not find the issuer rules file.") except ValueError: print("Error: Please enter a valid numeric card number.") if __name__ == "__main__": main()
Example Issuer Rules File
Make sure your rules file (card_issuers.txt) uses the format IssuerName:PrefixRanges:ValidLengths—here’s a sample:
MasterCard:55-59,2221-2720:16 Visa:4:13,16 American Express:34,37:15 Discover:6011,622126-622925,644-649,65:16
Key Fixes Explained
- Targeted Matching: We now check both the card’s prefix (for the correct length of the issuer’s range) and its total length before adding an issuer to results.
- Efficient Filtering: The loop skips issuers that don’t match the card length immediately, saving unnecessary checks.
- Robust Parsing: The rules loader handles comments, blank lines, and both single-value and range-based prefixes.
When you input 5558397375275489, this script will only return MasterCard as the issuer (since it matches the 55-59 prefix and 16-digit length) plus the Luhn validation result.
内容的提问来源于stack exchange,提问作者program noob

