Tôi đã cào 800 nghìn dữ liệu điểm thi đại học 2019 như thế nào
TIL
720
White

votinhthuong viết ngày 21/07/2019

Tôi đã cào 800 nghìn dữ liệu điểm thi đại học 2019 như thế nào

Cách đây vài ngày, vào một buổi sáng sớm tinh mơ, tôi có nằm lướt Facebook buổi sáng. Vô tình một post khá ấn tượng đập vào mắt. Có một thành viên trong cộng đồng Machine Learning mà tôi tham gia, post một bài viết chia sẻ source code cho project về phân tích điểm thi đại học năm 2019. Hôm ấy tôi cũng có mày mò tải về, dựng máy ảo để chạy thử. Nhưng kết quả thất bại! Code liên tục báo lỗi rất nhiều đoạn, mặc dù tôi đã làm các bước chuẩn bị đầy đủ, rồi kiểm tra phiên bản này nọ,.. nhưng không có cái nào làm nó chạy cả. Mà bản thân cái post cũng là quảng cáo cho một cái gì đó khác, trong source code chia sẻ cũng có nhắc nhiều về nó, nên tôi mơ hồ đoán được đồ miễn phí chưa chắc đã miễn phí. Nên thôi, quyết định của tôi lúc đó là tự code luôn cho sướng.
alt
Bài viết này tôi không đề cập tới phần phân tích dữ liệu, nó sẽ nằm trong một bài viết khác. Hoặc có thể là không có bài viết nào về nó, vì kiến thức Machine Learning hay Data Analyst của tôi vẫn là con số 0 tròn trĩnh hahaha…. Tôi chỉ đề cập tới vấn đề cấp thiết nhất của bài toán này, đó là làm cách nào để có dữ liệu đầu vào đầy đủ nhất, trọn vẹn nhất, để làm tập dữ liệu đầu vào cho vấn đề phân tích sau này.
alt
Khác với các lần trước, lần này tôi tự thấy tôi có một bước tiến hơn so với các lần trước. Đó là tôi không dùng thư viện PHP Simple HTML DOM Parser để làm công việc thu thập dữ liệu nữa. Thay vào đó, tôi dùng Python, kết hợp thư viện Beautiful Soup nổi tiếng để làm việc này. Và quyết định này thật sự không uổng phí, vì nó giải quyết được rất nhiều vấn đề về thời gian và công sức để parse dữ liệu.
alt
Đầu tiên tôi cần chuẩn bị mọi thứ thật tốt trước rồi mới xắn tay áo lên để làm được. Kể từ lúc thi xong đại học và học đại học, tôi đã hoàn toàn không còn quan tâm tới vấn đề này nữa. Mọi sự ra sao cũng được, tôi không để ý tới nữa.

“Tri vong thị phi, tâm chi thích dã”

Sau khi research một vòng với vài từ khóa đơn giản, tôi thấy được có rất nhiều trang hỗ trợ lấy thông tin điểm thi của sinh viên. Điều thú vị là các thông tin cá nhân đã được lược bỏ đi hết rồi, chỉ còn lại số báo danh và điểm thi thôi. Như vậy cũng không sao. Chủ yếu ta chỉ cần có thông tin điểm thi để phân tích thôi. Sau khi tìm được trang để get thông tin, tôi thử tìm với một số báo danh (SBD) bất kỳ và thu được kết quả là một table với các cột và dòng về điểm thi. Thử xem phần tử, tôi thấy được bảng này được đặt tên cụ thể, các thông tin về điểm thi được đặt trong các thẻ <td> rất chi tiết. Như vậy là khả quan rồi.

alt

Tiếp theo, tôi tiến hành tạo một máy ảo chạy Ubuntu để chạy code Python. Bạn hoàn toàn có thể dùng bất kỳ OS nào bạn thích để chạy Python, tôi chọn Ubuntu chẳng qua vì nó có sẵn Python rồi, việc cài đặt các gói cần thiết cũng dễ dàng. Lưu ý là từ bản Ubuntu 18.04 trở đi, tôi thấy nó bị lược bỏ đi hay sao ấy, phải cài đặt trước rồi mới dùng được. Tốt nhất là dùng bản 16.04, vẫn ngon lành!

alt

Về ý tưởng code, tôi cũng code theo suy nghĩ dàn trải chứ không có kế hoạch từ đầu. Cụ thể lúc đầu tôi chỉ cắm đầu vào code sao cho nó get được thông tin về đúng như mong muốn trước đã, rồi sau đó mới tính tiếp tới chuyện get hàng loạt, ghi vào file CSV,…
Muốn làm được việc get thông tin từ trang web như vậy, tôi dùng thư việnBeautiful Soup nổi tiếng chuyên phục vụ cho việc Web Scraping này. Để cài đặt trong Ubuntu, ta chỉ việc gõ vào terminal lệnh:

apt-get install python-bs4

Đầu tiên, tôi cần tạo ra một file CSV chứa các trường thông tin như SBD, điểm thi các môn. Nếu thí sinh nào không thi môn đó thì bỏ qua, không cần điền vào.

with open('myreport.csv','wb') as f:
thewriter = csv.writer(f, delimiter=',', quoting=csv.QUOTE_ALL)
thewriter.writerow(['SBD','Toan','Van','Ngoai ngu','Vat li','Hoa hoc','Sinh hoc','Lich su','Dia li','GDCD'])

Tiếp theo, tôi sẽ cho chạy vòng lặp. Bên trong đó, tương ứng với số i của vòng lặp khi chạy, cũng chính là giá trị SBD được chuyển vào url của trang web đích. Như vậy mỗi lần lặp sẽ tương ứng một SBD. Nếu số đó tồn tại, tức là table kết quả tồn tại. Nếu SBD không tồn tại, sẽ không có bảng table được trả về. Căn cứ vào đó, tôi cho chạy mệnh đề if else.
Với mỗi URL được truy cập, kiểm tra xem có tồn tại bảng kết quả điểm thi hay không. Nếu có, ta sẽ xử lý tiếp các công việc tìm các thẻ <td> và thẻ chứa SBD. Sau đó, ghi vào file CSV theo các cột tương ứng. Nếu không thấy có bảng cần tìm, ta chỉ việc cho qua (sử dụng từ khóa pass).

for x in range(<first_value>,<end_value>):
URL = ‘url_web'+str(x)
content = requests.get(URL)
soup = BeautifulSoup(content.text, 'html.parser')
contentTable = soup.find('table', { 'class':'table thpt-mobile hidden-md hidden-sm hidden-lg'})
my_list = []
if(contentTable is not None):
rows = contentTable.find_all('tr')
contentSBD = soup.find('p', attrs={'class':'SoBD m-t-10'})
for span in contentSBD.find_all('span', recursive=False):
my_list.append(span.text)
for row in rows:
content1 = row.find_all('td')[1::2]
for values in content1:
my_list.append(values.get_text())
thewriter.writerow(my_list)
else:
pass

Một điều thú vị ở đây nữa, đó là do duyệt qua rất nhiều lần với lượt SBD lên đến hàng trăm nghìn, tôi quyết định thêm vào code của mình một phần nhỏ, để xác định xem code chạy trong bao lâu.

print(datetime.datetime.now())
start = time.time()
end = time.time()
print(datetime.datetime.now())
time = end-start
day = time // (24 * 3600)
time = time % (24 * 3600)
hour = time // 3600
time %= 3600
minutes = time // 60
time %= 60
seconds = time
print("d:h:m:s-> %d:%d:%d:%d" % (day, hour, minutes, seconds))

Như vậy, khi khởi chạy, code sẽ in ra thời gian bắt đầu, và thời gian kết thúc, đồng thời tính xem ta tốn bao nhiêu thời gian để thu thập toàn bộ dữ liệu cần có.

alt

Một điều nữa là sau khi xong xuôi, tôi có lượn qua một vài trang khác để tham khảo, thì phát hiện một chi tiết thú vị. Với một trang web khác cũng hỗ trợ cho tra cứu điểm thi, ngoài việc trả về kết quả điểm thi, nếu bạn bấm vào SBD đó, bạn còn có thể biết được thí sinh đó thi ở cụm nào, và danh sách các trường gợi ý cho thí sinh đó. Cực kỳ hay!

Bình luận


White
{{ comment.user.name }}
Bỏ hay Hay
{{comment.like_count}}
Male avatar
{{ comment_error }}
Hủy
   

Hiển thị thử

Chỉnh sửa

White

votinhthuong

1 bài viết.
1 người follow
Kipalog
{{userFollowed ? 'Following' : 'Follow'}}
Bài viết liên quan
White
0 4
fCC: Technical Documentation Page note So I have finished the HTML part of this exercise and I want to come here to lament about the lengthy HTML ...
HungHayHo viết 1 năm trước
0 4
White
2 0
I used Spring boot, Hibernate few times back then at University, I'v started using it again recently. In this (Link), I want to check how Spring J...
Rey viết 7 tháng trước
2 0
White
22 1
Toán tử XOR có tính chất: + A XOR A = 0 + 0 XOR A = A Với tính chất này, có thể cài đặt bài toán sau với độ phức tạp O(N) về runtime, và với O(1)...
kiennt viết gần 3 năm trước
22 1
{{like_count}}

kipalog

{{ comment_count }}

bình luận

{{liked ? "Đã kipalog" : "Kipalog"}}


White
{{userFollowed ? 'Following' : 'Follow'}}
1 bài viết.
1 người follow

 Đầu mục bài viết

Vẫn còn nữa! x

Kipalog vẫn còn rất nhiều bài viết hay và chủ đề thú vị chờ bạn khám phá!