Ngân hàng câu hỏi của chương

Câu hỏi: PRP201c - Phần 3: Thu thập và trao đổi dữ liệu web

43 câu trắc nghiệm kèm lời giải của môn PRP201c - Lập trình Python, xếp theo thứ tự nhập vào ngân hàng.

Danh sách câu hỏi

20/43 câuCòn 23
Đề bài
<a>
  <b>X</b>
  <c>
    <d>Y</d>
    <e>Z</e>
  </c>
</a>
Ab
Ba
Cc
De
Lời giải
Đáp án đúng: "c". Trong XML, các phần tử lồng nhau tạo thành cây; nút cha (parent node) của một nút là phần tử bao trực tiếp nó, tức thẻ mở gần nhất chưa đóng ngay phía trên nó. Thẻ e nằm giữa thẻ mở và thẻ đóng của c, cùng cấp với d, nên c là cha trực tiếp của e còn d là anh em (sibling) của e. Chọn "b" là sai vì b chỉ chứa chữ X và đã đóng trước khi c mở, nên b là anh em của c chứ không bao e. Chọn "a" là sai vì a là nút gốc, chỉ là tổ tiên (ancestor) của e qua trung gian c, không phải cha trực tiếp. Chọn "e" là sai vì một nút không thể là cha của chính nó; e chỉ chứa nút văn bản Z.
Mở trang câu hỏi này →
Atn.read_until(b"Login:")
Btn.read_until(b"user: ")
Ctn.read_until(b"user:")
Dtn.read_until(b"Username: ")
Lời giải
Đáp án đúng: "tn.read_until(b"Username: ")". Câu hỏi dùng module telnetlib: sau khi tạo đối tượng tn = telnetlib.Telnet(host), phương thức read_until đọc dữ liệu từ kết nối cho tới khi gặp đúng chuỗi byte được chỉ định, nên phải truyền đúng dấu nhắc (prompt) mà thiết bị in ra; router Cisco khi bật xác thực đăng nhập in dấu nhắc mặc định là chữ Username, dấu hai chấm và một dấu cách, sau đó script mới gửi tên người dùng bằng tn.write. Trong Python 3 đối số phải là kiểu bytes nên có tiền tố b. "tn.read_until(b"Login:")" chờ chuỗi Login mà router Cisco không in theo mặc định, nên lệnh sẽ đứng chờ tới hết thời gian chờ. "tn.read_until(b"user: ")" sai chữ: read_until so khớp từng byte và phân biệt hoa thường, mà dấu nhắc thật bắt đầu bằng U hoa và có chữ name. "tn.read_until(b"user:")" sai tương tự, lại thiếu cả dấu cách sau dấu hai chấm. Lưu ý telnetlib bị đánh dấu lỗi thời từ Python 3.11 và đã bị gỡ khỏi thư viện chuẩn ở Python 3.13 (PEP 594), nên mã này chỉ chạy trên phiên bản cũ hơn; ngày nay thường dùng SSH qua Paramiko hoặc Netmiko.
Mở trang câu hỏi này →
AUTF-128
BUTF-8
CUTF-32
DUTF-64
Lời giải
Đáp án đúng: "UTF-8". Khi trao đổi dữ liệu giữa các hệ thống qua mạng, tệp hay API, UTF-8 là bảng mã Unicode phổ biến nhất vì nó mã hoá mỗi ký tự bằng 1 đến 4 byte với độ dài thay đổi, tương thích ngược với ASCII (chữ tiếng Anh vẫn chiếm đúng 1 byte) và không phụ thuộc thứ tự byte của máy; trong Python 3, encode() và decode() mặc định dùng UTF-8. "UTF-32" là mã hoá Unicode có thật nhưng dùng cố định 4 byte cho mọi ký tự, tốn dung lượng nên chủ yếu dùng nội bộ khi cần truy cập ký tự theo chỉ số, hiếm khi dùng để truyền dữ liệu. "UTF-128" không tồn tại; con số 128 dễ làm nhớ tới 128 ký tự của bảng ASCII chứ không phải một đơn vị mã hoá. "UTF-64" cũng không tồn tại: Unicode chỉ định nghĩa UTF-8, UTF-16 và UTF-32, và không gian mã chỉ tới U+10FFFF nên 32 bit đã thừa chỗ.
Mở trang câu hỏi này →
Afind()
Bencode()
Cdecode()
Dupper()
Lời giải
Đáp án đúng: "decode()". Dữ liệu đọc từ mạng, chẳng hạn qua urllib.request.urlopen hay socket.recv, đến dưới dạng bytes: chuỗi byte thô, thường mã hoá theo UTF-8. Trong Python 3, kiểu str bên trong là chuỗi Unicode, nên phải gọi decode() trên đối tượng bytes để chuyển thành str, ví dụ line.decode().strip(). "find()" là phương thức tìm vị trí xuất hiện đầu tiên của một chuỗi con và trả về chỉ số hoặc -1, không đổi định dạng dữ liệu. "encode()" làm điều ngược lại: biến str thành bytes, dùng khi gửi đi, như lúc gửi lệnh GET qua socket, nên dùng cho dữ liệu nhận về là sai chiều. "upper()" chỉ chuyển chữ thường thành chữ hoa và giữ nguyên kiểu dữ liệu; gọi nó trên bytes vẫn trả về bytes chứ không thành str.
Mở trang câu hỏi này →
ADocument-Type:
BContent-Type:
CMetadata:
DETag:
EHTML-Document:
Lời giải
Đáp án đúng: "Content-Type:". Trong giao thức HTTP, phản hồi (response) của máy chủ gồm các dòng header đứng trước phần thân; header Content-Type cho trình duyệt biết kiểu MIME của tài liệu trả về, ví dụ text/html; charset=utf-8 hay image/png, để trình duyệt quyết định hiển thị nó như trang web, ảnh hay văn bản thường. Phương án "Document-Type:" không phải header chuẩn của HTTP; dễ nhầm với khai báo DOCTYPE nằm bên trong chính tài liệu HTML. Phương án "Metadata:" cũng không phải header chuẩn, chỉ là từ chung chỉ dữ liệu mô tả. Phương án "ETag:" là header có thật nhưng mang mã định danh phiên bản của tài nguyên để phục vụ bộ nhớ đệm (cache), không cho biết kiểu tài liệu. Phương án "HTML-Document:" không tồn tại; hơn nữa một phản hồi có thể là JSON hay ảnh chứ không chỉ là HTML.
Mở trang câu hỏi này →
A80
B25
C110
D443
Lời giải
Đáp án đúng: "80". Theo danh sách cổng do IANA quản lý, HTTP (giao thức truyền siêu văn bản) chạy trên cổng TCP 80; khi một URL bắt đầu bằng http và không ghi số cổng, trình duyệt và urllib tự kết nối tới cổng 80, giống ví dụ socket kinh điển mysock.connect(('data.pr4e.org', 80)). Số cổng cho máy chủ biết dịch vụ nào sẽ trả lời kết nối. "443" là cổng mặc định của HTTPS, tức HTTP chạy trên lớp mã hoá TLS, không phải HTTP thường. "25" là cổng của SMTP, giao thức các máy chủ thư dùng để chuyển thư điện tử cho nhau. "110" là cổng của POP3, giao thức để chương trình đọc thư tải thư từ máy chủ về máy người dùng. Nhớ các cổng phổ biến này giúp đọc đúng các đoạn mã socket gửi yêu cầu thủ công.
Mở trang câu hỏi này →
AThat the web site supports the HTTP GET command
BThat the web site allows scraping
CThat the web site returns HTML for all pages
DThat the web site only has links
Lời giải
Đáp án đúng: "That the web site allows scraping". Thu thập dữ liệu web (web scraping) là dùng chương trình tự động tải trang và bóc nội dung; trước khi làm cần kiểm xem trang có cho phép hay không, qua điều khoản sử dụng (terms of service) và tệp robots.txt, vì nhiều trang cấm truy cập tự động hoặc giới hạn tốc độ, vi phạm có thể bị chặn hoặc gặp rắc rối pháp lý. Phương án "That the web site supports the HTTP GET command" sai vì GET là phương thức cơ bản mà mọi máy chủ web đều hỗ trợ để trả trang, không có gì phải kiểm. Phương án "That the web site returns HTML for all pages" không cần thiết: trang có thể trả JSON, ảnh hay PDF và chương trình vẫn xử lý được theo từng loại. Phương án "That the web site only has links" không liên quan tới việc được phép thu thập, và một trang chỉ toàn liên kết thì cũng chẳng có nội dung gì đáng lấy.
Mở trang câu hỏi này →
A!
B*
C^
D/
Lời giải
Đáp án đúng: "*". Bảng mã ASCII gán mỗi ký tự một số nguyên từ 0 đến 127; giá trị thập phân 42 ứng với dấu sao. Trong Python có thể kiểm bằng chr(42) trả về '*' và ord('*') trả về 42. Các ký tự lân cận: 40 và 41 là hai dấu ngoặc tròn, 43 là dấu cộng. "!" là dấu chấm than, mang mã 33, ký tự in được đầu tiên sau dấu cách (32). "^" là dấu mũ, mang mã 94, nằm sau các chữ hoa và dấu ngoặc vuông. "/" là dấu gạch chéo, mang mã 47, đứng ngay trước chữ số 0 (mã 48). Nhớ vài mốc như dấu cách là 32, chữ số 0 là 48, chữ hoa đầu bảng chữ cái là 65 và chữ thường đầu bảng là 97 giúp suy ra nhanh vị trí các ký tự khác.
Mở trang câu hỏi này →
A[b'd', b'e', b'f']
Bb'def'
C[100, 101, 102]
DIt raises an exception
Lời giải
Đáp án đúng: "It raises an exception". Biểu thức trong ngoặc được tính trước: b'abcde' là đối tượng bytes còn 'fghi' là chuỗi str, và Python 3 không cho nối hai kiểu này bằng dấu cộng, nên ngay bước b'abcde' + 'fghi' đã phát sinh TypeError (can't concat str to bytes); lát cắt [3:6] và list() không bao giờ được chạy. "[100, 101, 102]" là kết quả nếu vế sau cũng là bytes b'fghi', vì phần tử của bytes khi lấy ra là số nguyên mã byte (d = 100, e = 101, f = 102). "b'def'" là kết quả của lát cắt b'abcdefghi'[3:6] nếu không bọc list(). "[b'd', b'e', b'f']" sai cả trong trường hợp nối được, vì duyệt bytes cho số nguyên chứ không cho các bytes một ký tự. Muốn nối hợp lệ phải mã hoá chuỗi bằng 'fghi'.encode().
Mở trang câu hỏi này →
Aurlopen()
Bconnect()
Crequest()
Dreadurl()
Lời giải
Đáp án đúng: "urlopen()". Trong Python 3, urllib.request.urlopen(url) mở kết nối HTTP, gửi yêu cầu GET và trả về một đối tượng giống tệp (file-like object): có thể lặp từng dòng hoặc gọi read() để lấy nội dung dạng bytes, rồi decode() thành chuỗi; urllib tự lo phần socket và header thay cho người lập trình. "connect()" là phương thức của đối tượng socket, chỉ mở kết nối TCP tới một máy chủ và cổng, không tự gửi yêu cầu hay lấy nội dung trang. "request()" không phải hàm của urllib: urllib.request là tên module con chứa urlopen, còn Request là lớp dùng để dựng một yêu cầu rồi truyền vào urlopen, tự nó không trả về nội dung. "readurl()" không tồn tại trong urllib; việc đọc nội dung được thực hiện bằng read() trên đối tượng mà urlopen trả về.
Mở trang câu hỏi này →
AIt's syntax is simpler and aligns with JavaScript
BIt is more verbose
CIt is human-unreadable
DIt requires no formatting
Lời giải
Đáp án đúng: "It's syntax is simpler and aligns with JavaScript". JSON (JavaScript Object Notation) biểu diễn dữ liệu bằng đối tượng, mảng, chuỗi và số theo đúng cú pháp literal của JavaScript, không cần thẻ mở thẻ đóng như XML, nên gọn hơn, dễ phân tích và ánh xạ thẳng sang dict, list trong Python (qua json.loads); vì vậy JSON được ưa dùng cho REST API. "It is more verbose" sai vì dài dòng (verbose) là nhược điểm của XML với các thẻ lặp tên, và nếu đúng thì đó cũng không phải ưu điểm. "It is human-unreadable" sai vì JSON là văn bản thuần, người đọc được dễ dàng. "It requires no formatting" sai vì JSON có quy tắc định dạng chặt: khoá phải đặt trong nháy kép, không có dấu phẩy thừa, chuỗi dùng nháy kép; sai định dạng thì bộ phân tích báo lỗi.
Mở trang câu hỏi này →
Arequests.tail('https://httpbin.org/tail')
Brequests.put('https://httpbin.org/put', data={'key':'value'})
Crequests.put('https://httpbin.org/tail')
Drequests.get('https://httpbin.org/put', data={'key':'value'})
Lời giải

Đáp án đúng: "

Lời giải
requests.put('https://httpbin.org/put', data={
  'key':'value'
}

)". Thư viện requests cung cấp mỗi phương thức HTTP thành một hàm cùng tên: get, post, put, delete, head, patch, options. Dịch vụ httpbin gắn mỗi đường dẫn với đúng phương thức của nó: /put chỉ nhận yêu cầu PUT và gửi lại nội dung đã nhận, nên gọi requests.put tới /put kèm data là yêu cầu khớp cả hàm lẫn đường dẫn. "requests.tail('https://httpbin.org/tail')" sai vì HTTP không có phương thức TAIL và requests không có hàm tail, Python báo AttributeError trước khi gửi gì đi. "requests.put('https://httpbin.org/tail')" gọi đúng hàm nhưng httpbin không có đường dẫn /tail, máy chủ trả mã 404 Not Found. "

Lời giải
requests.get('https://httpbin.org/put', data={
  'key':'value'
}

)" dùng GET cho đường dẫn chỉ nhận PUT nên bị trả mã 405 Method Not Allowed; ngoài ra GET thường không mang thân dữ liệu, tham số của GET nên đặt trong params.

Mở trang câu hỏi này →
A++
B$
C?
D^
Lời giải
Đáp án đúng: "?". Trong biểu thức chính quy (regular expression), + và * mặc định là tham lam (greedy): chúng khớp chuỗi dài nhất có thể. Thêm dấu chấm hỏi ngay sau chúng thành +? hoặc *? biến chúng thành không tham lam (non-greedy), khớp chuỗi ngắn nhất thoả mẫu; ví dụ re.findall('^F.+?:', 'From: Using the :') cho ['From:'] thay vì cả đoạn tới dấu hai chấm cuối. "++" sai vì trong mô-đun re dấu cộng đôi chỉ được hỗ trợ từ Python 3.11 và mang nghĩa possessive (chiếm hữu, không quay lui), không phải non-greedy. "$" sai vì nó neo vị trí cuối chuỗi hoặc cuối dòng. "^" sai vì nó neo đầu chuỗi, hoặc trong ngoặc vuông như [^a] thì mang nghĩa phủ định tập ký tự.
Mở trang câu hỏi này →
AAn "in-progress" phone conversation
BFiber optic cables
CThe wheels on an automobile
DThe chain on a bicycle
EThe ringer on a telephone
Lời giải
Đáp án đúng: "An "in-progress" phone conversation". Socket (ổ cắm mạng) là điểm cuối của một kết nối hai chiều giữa hai chương trình: sau khi connect thành công, hai bên có thể lần lượt gửi bằng send và nhận bằng recv cho tới khi một bên gọi close, giống hệt một cuộc gọi điện thoại đang diễn ra mà hai người nói qua nói lại cho tới lúc gác máy. "Fiber optic cables" là phương tiện truyền vật lý ở tầng thấp nhất, tương ứng với đường dây chứ không phải kết nối logic giữa hai ứng dụng. "The wheels on an automobile" là bộ phận cơ khí lăn trên đường, không có hai đầu trao đổi thông tin với nhau. "The chain on a bicycle" chỉ truyền lực một chiều từ bàn đạp tới bánh xe, không phải kênh trao đổi qua lại. "The ringer on a telephone" chỉ là chuông báo có cuộc gọi tới, giống tín hiệu chờ kết nối chứ chưa phải cuộc trò chuyện đang mở.
Mở trang câu hỏi này →
AMatch any number of lowercase letters followed by any number of digits
BMatch a lowercase letter or a digit
CMatch an entire line as long as it is lowercase letters or digits
DMatch any text that is surrounded by square braces
Lời giải
Đáp án đúng: "Match a lowercase letter or a digit". Trong biểu thức chính quy (regular expression), cặp ngoặc vuông tạo một lớp ký tự (character class) khớp đúng MỘT ký tự thuộc tập liệt kê; a-z là dải chữ thường, 0-9 là dải chữ số, nên [a-z0-9] khớp một ký tự là chữ thường hoặc chữ số. Muốn khớp nhiều ký tự phải thêm lượng từ như + hay * phía sau. "Match any number of lowercase letters followed by any number of digits" sai vì lớp ký tự không có thứ tự trước sau và không lặp; mẫu đó phải viết [a-z]*[0-9]*. "Match an entire line as long as it is lowercase letters or digits" cần thêm neo đầu dòng, neo cuối dòng cùng lượng từ, tức ^[a-z0-9]+$. "Match any text that is surrounded by square braces" sai vì ngoặc vuông ở đây là cú pháp chứ không phải ký tự cần khớp; muốn khớp ngoặc vuông thật phải thoát nó bằng dấu gạch ngược.
Mở trang câu hỏi này →
AREST uses formatted text (JSON)
BREST sends binary only
CSocket always encrypts data
DREST uses formatted text (HTML)
Lời giải
Đáp án đúng: "REST uses formatted text (JSON)". Khi gọi một REST API (giao diện lập trình theo kiến trúc REST), dữ liệu được đóng gói trong yêu cầu và phản hồi HTTP, và nội dung thường là văn bản có cấu trúc dạng JSON (JavaScript Object Notation), khai báo qua header Content-Type là application/json, nên Python đọc bằng json.loads; còn socket thô chỉ truyền một dòng byte, ứng dụng hai đầu tự quy ước định dạng. "REST sends binary only" sai vì REST chạy trên HTTP và chủ yếu trao đổi văn bản; có thể gửi dữ liệu nhị phân như ảnh hay tệp nhưng không phải chỉ nhị phân. "Socket always encrypts data" sai vì socket TCP gửi dữ liệu thô, không mã hoá; muốn mã hoá phải bọc thêm TLS bằng module ssl. "REST uses formatted text (HTML)" lệch trọng tâm: HTML là định dạng trang web để hiển thị cho người đọc, còn API trả dữ liệu cho chương trình xử lý, nên chủ yếu dùng JSON, trước đây có cả XML.
Mở trang câu hỏi này →
Aconnect
Bresend
Creject
Ddisconnect
Lời giải
Đáp án đúng: "connect". Lời gọi chặn (blocking call) là lời gọi khiến chương trình dừng lại chờ tới khi thao tác hoàn tất mới trả về. Với socket ở chế độ mặc định, connect() chặn cho tới khi bắt tay ba bước của TCP xong hoặc thất bại; tương tự recv() chặn chờ dữ liệu và accept() chặn chờ kết nối tới. Câu hỏi viết ở số nhiều nhưng chỉ có connect là lời gọi chặn chuẩn, nên chỉ chọn một. "resend" không phải phương thức của socket; việc gửi lại gói tin bị mất do TCP tự làm bên trong hệ điều hành, chương trình không gọi. "reject" cũng không phải lời gọi socket; máy chủ từ chối kết nối bằng cách không lắng nghe hoặc đóng kết nối, phía khách nhận ConnectionRefusedError. "disconnect" không tồn tại trong module socket; ngắt kết nối dùng close() hoặc shutdown(), và ở chế độ mặc định chúng trả về ngay chứ không chờ sự kiện.
Mở trang câu hỏi này →
AOne or more digits
BSeveral digits followed by a plus sign
CAny mathematical expression
DAny number of digits at the beginning of a line
EZero or more digits
Lời giải
Đáp án đúng: "One or more digits". Trong biểu thức chính quy (regular expression), [0-9] là một lớp ký tự (character class) khớp đúng một chữ số từ 0 tới 9, còn dấu + đứng sau nghĩa là phần đứng trước được lặp một lần trở lên; ghép lại, [0-9]+ khớp một dãy liền gồm ít nhất một chữ số, như 7 hay 2024. Phương án "Several digits followed by a plus sign" sai vì + ở đây là ký tự đặc biệt chỉ số lần lặp; muốn khớp dấu cộng thật phải thoát thành \+. Phương án "Any mathematical expression" sai vì mẫu chỉ khớp chữ số, không khớp toán tử hay khoảng trắng. Phương án "Any number of digits at the beginning of a line" sai vì mẫu không có ký tự neo ^ nên có thể khớp ở bất kỳ vị trí nào trong dòng. Phương án "Zero or more digits" mô tả mẫu [0-9]* dùng dấu sao, chứ không phải dấu cộng.
Mở trang câu hỏi này →
Asocket.sendto(address, data)
Bsocket.address()
Csocket.sendto(data, address)
Dsocket.data
Lời giải
Đáp án đúng: "socket.sendto(data, address)". Với socket UDP (SOCK_DGRAM) không có kết nối cố định, phương thức sendto của đối tượng socket gửi dữ liệu tới một địa chỉ chỉ định trong từng lần gọi; theo tài liệu Python, đối số đầu là dữ liệu dạng bytes, đối số sau là địa chỉ, thường là tuple (host, port), ví dụ s.sendto(b'hello', ('127.0.0.1', 9999)). "socket.sendto(address, data)" sai vì đảo thứ tự đối số; truyền tuple địa chỉ vào chỗ dữ liệu sẽ gây TypeError. "socket.address()" sai vì socket không có phương thức address; lấy địa chỉ dùng getsockname() hoặc getpeername(). "socket.data" sai vì đây không phải lời gọi phương thức và socket không có thuộc tính data; nhận dữ liệu dùng recv hoặc recvfrom.
Mở trang câu hỏi này →
Ainverted
BUnicode
CEBCDIC
DUTF-16
Ebubble memory
Lời giải
Đáp án đúng: "Unicode". Trong Python 3 mọi chuỗi str đều là chuỗi Unicode: mỗi phần tử là một điểm mã (code point) Unicode, nên chuỗi tiếng Việt hay tiếng Nhật được xử lý như nhau; còn dữ liệu byte thô là kiểu bytes riêng, phải encode/decode (thường bằng UTF-8) khi đọc ghi mạng hoặc tệp. Đây là khác biệt lớn so với Python 2, nơi str mặc định là byte. "UTF-16" sai vì đó là một cách mã hoá cụ thể; từ Python 3.3 (PEP 393), CPython lưu chuỗi theo biểu diễn linh hoạt 1, 2 hoặc 4 byte mỗi ký tự tuỳ ký tự lớn nhất, không cố định UTF-16. "EBCDIC" sai vì đó là bảng mã cũ của máy IBM, không dùng cho chuỗi Python. "inverted" sai vì không có cách lưu "đảo ngược" nào. "bubble memory" sai vì đó là một công nghệ bộ nhớ phần cứng cũ, không phải cách mã hoá chuỗi.
Mở trang câu hỏi này →