Làm cách nào để đọc nội dung HTML bằng Python?

Đối với ví dụ đầu tiên, chúng tôi sẽ cố gắng phân tích bảng này từ phần Chính trị trên trang wiki Minnesota

Làm cách nào để đọc nội dung HTML bằng Python?

Cách sử dụng cơ bản của pandas

1
0 khá đơn giản và hoạt động tốt trên nhiều trang Wikipedia vì các bảng không phức tạp. Để bắt đầu, tôi sẽ bao gồm một số lần nhập bổ sung mà chúng tôi sẽ sử dụng để làm sạch dữ liệu cho các ví dụ phức tạp hơn

import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
from unicodedata import normalize

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota')

Điểm độc đáo ở đây là

1
1 là danh sách tất cả các bảng trên trang

print(f'Total tables: {len(table_MN)}')

Total tables: 38

Với 38 bàn, có thể khó tìm được bàn bạn cần. Để làm cho việc lựa chọn bảng dễ dàng hơn, hãy sử dụng tham số

1
2 để chọn một tập hợp con các bảng. Chúng ta có thể sử dụng chú thích “Kết quả bầu cử từ các cuộc tranh cử trên toàn tiểu bang” để chọn bảng

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota', match='Election results from statewide races')
len(table_MN)

1

________số 8_______

YearOffice GOPDFL Others02018Governor42. 4%53. 9%3. 7%12018Thượng nghị sĩ36. 2%60. 3%3. 4%22018Thượng nghị sĩ42. 4%53. 0%4. 6%32016Chủ tịch44. 9%46. 4%8. 6%42014Governor44. 5%50. 1%5. 4%

Pandas giúp dễ đọc trong bảng và cũng xử lý cột năm kéo dài nhiều hàng. Đây là một ví dụ cho thấy việc sử dụng gấu trúc dễ dàng hơn là cố gắng tự mình loại bỏ tất cả

Nhìn chung, điều này có vẻ ổn cho đến khi chúng tôi xem xét các loại dữ liệu với

1
3

'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB

Chúng tôi cần chuyển đổi GOP , DFL và .

Nếu chúng ta cố gắng

df['GOP'].astype('float')

Chúng tôi gặp lỗi

ValueError: could not convert string to float: '42.4%'

Thủ phạm có khả năng nhất là

1
4. Chúng ta có thể loại bỏ nó bằng hàm pandas
1
5. Tôi đã đề cập đến điều này một số chi tiết trong một bài viết trước

df['GOP'].replace({'%':''}, regex=True).astype('float')

Cái nào có vẻ tốt

print(f'Total tables: {len(table_MN)}')
0

Lưu ý rằng tôi phải sử dụng tham số

1
6 để tham số này hoạt động vì
1
4 là một phần của chuỗi chứ không phải giá trị chuỗi đầy đủ

Bây giờ, chúng ta có thể gọi thay thế tất cả các giá trị

1
4 và chuyển đổi thành số bằng cách sử dụng
1
9 và
df = table_MN[0]
df.head()
0

print(f'Total tables: {len(table_MN)}')
1

print(f'Total tables: {len(table_MN)}')
2

print(f'Total tables: {len(table_MN)}')
3

YearOffice GOPDFL Others02018Governor42. 453. 93. 712018Thượng nghị sĩ36. 260. 33. 422018Thượng nghị sĩ42. 453. 04. 632016Chủ tịch44. 946. 48. 642014Governor44. 550. 15. 4

Quá trình cơ bản này hoạt động tốt. Ví dụ tiếp theo phức tạp hơn một chút

Làm sạch dữ liệu nâng cao hơn

Ví dụ trước cho thấy các khái niệm cơ bản. Thường xuyên làm sạch nhiều hơn là cần thiết. Đây là một ví dụ phức tạp hơn một chút. Ví dụ này tiếp tục sử dụng Wikipedia nhưng các khái niệm áp dụng cho bất kỳ trang web nào có dữ liệu trong bảng HTML .

Điều gì sẽ xảy ra nếu chúng tôi muốn phân tích bảng Hoa Kỳ GDP bên dưới?

Làm cách nào để đọc nội dung HTML bằng Python?

Cái này khó sử dụng đối sánh hơn một chút để chỉ có một bảng nhưng đối sánh trên 'Danh nghĩa GDP ' sẽ có được bảng mà chúng tôi muốn .

print(f'Total tables: {len(table_MN)}')
4

print(f'Total tables: {len(table_MN)}')
5

Không có gì ngạc nhiên khi chúng tôi có một số công việc dọn dẹp phải làm. Chúng tôi có thể cố gắng xóa

1
4 như chúng tôi đã làm lần trước

print(f'Total tables: {len(table_MN)}')
6

Rất tiếc, chúng tôi gặp lỗi này

print(f'Total tables: {len(table_MN)}')
7

Vấn đề ở đây là chúng tôi có một ký tự ẩn,

df = table_MN[0]
df.head()
2 đang gây ra một số lỗi. Đây là “dấu cách Latin1 ( ISO 8859-1) không vi phạm”.

Một tùy chọn mà tôi đã sử dụng là loại bỏ trực tiếp giá trị bằng cách sử dụng

df = table_MN[0]
df.head()
3. Nó hoạt động nhưng tôi lo lắng về việc liệu nó có bị phá vỡ với các ký tự khác trong tương lai hay không

Sau khi đi xuống hố thỏ unicode, tôi quyết định sử dụng

df = table_MN[0]
df.head()
4 để làm sạch giá trị này. Tôi khuyến khích bạn đọc bài viết này để biết thêm chi tiết về lý do căn bản cho cách tiếp cận của tôi

Tôi cũng đã tìm thấy các vấn đề với khoảng trống thừa khi nhập dữ liệu trong một số bảng khác. Tôi đã tạo một chức năng nhỏ để xóa tất cả các giá trị văn bản. Tôi hy vọng những người khác sẽ thấy điều này hữu ích

print(f'Total tables: {len(table_MN)}')
8

Tôi có thể chạy chức năng này trên toàn bộ DataFrame bằng cách sử dụng

df = table_MN[0]
df.head()
5

print(f'Total tables: {len(table_MN)}')
9

df = table_MN[0]
df.head()
5 hiệu suất

Hãy thận trọng khi sử dụng

df = table_MN[0]
df.head()
5 Chức năng này rất chậm nên bạn nên thận trọng khi sử dụng nó

Hàm

df = table_MN[0]
df.head()
5 là một hàm gấu trúc rất kém hiệu quả. Bạn không nên sử dụng nó thường xuyên nhưng trong trường hợp này, DataFrame nhỏ và việc dọn dẹp như thế này rất khó nên tôi nghĩ đó là một sự đánh đổi hữu ích

Một điều mà

df = table_MN[0]
df.head()
5 bỏ lỡ là các cột. Hãy xem xét một cột chi tiết hơn

Total tables: 38
0

Total tables: 38
1

Chúng tôi có

'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB
0 đáng sợ đó trong tên cột. Có một số cách chúng ta có thể thực hiện để làm sạch các cột nhưng tôi sẽ sử dụng
'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB
1 trên các cột bằng cách chuyển đổi cột thành một chuỗi và sử dụng
'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB
2 để chạy hàm. Các phiên bản gấu trúc trong tương lai có thể làm điều này dễ dàng hơn một chút

Total tables: 38
2

Total tables: 38
3

Bây giờ chúng tôi đã xóa sạch một số ký tự ẩn. Tiếp theo là gì?

Hãy thử lại

print(f'Total tables: {len(table_MN)}')
6

Total tables: 38
5

cái này khó thật. Nếu quan sát thật kỹ, bạn có thể nhận ra rằng

'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB
3 trông hơi khác so với
'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB
4. Thật khó để thấy nhưng thực sự có một sự khác biệt giữa dấu gạch ngang unicode và dấu trừ. ừ

May mắn thay, chúng ta cũng có thể sử dụng

df = table_MN[0]
df.head()
3 để dọn sạch nó

Total tables: 38
6

Total tables: 38
7

Một cột khác mà chúng ta cần xem xét là cột

'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB
6. Đối với năm 2020, nó chứa “2020 (est)” mà chúng tôi muốn loại bỏ. Sau đó chuyển đổi cột thành int. Tôi có thể thêm vào từ điển nhưng phải thoát khỏi dấu ngoặc đơn vì chúng là các ký tự đặc biệt trong một biểu thức chính quy

Total tables: 38
8

Total tables: 38
9

Trước khi chúng tôi kết thúc và gán các giá trị này trở lại DataFrame của mình, có một mục khác cần thảo luận. Một số cột này phải là số nguyên và một số là số float. Nếu chúng tôi sử dụng

'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB
7, chúng tôi không có nhiều sự linh hoạt. Sử dụng
'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB
8, chúng tôi có thể kiểm soát loại số nhưng chúng tôi không muốn phải nhập số này theo cách thủ công cho mỗi cột

Hàm

'pandas.core.frame.DataFrame'>
RangeIndex: 24 entries, 0 to 23
Data columns (total 5 columns):
#   Column  Non-Null Count  Dtype
---  ------  --------------  -----
0   Year    24 non-null     int64
1   Office  24 non-null     object
2   GOP     24 non-null     object
3   DFL     24 non-null     object
4   Others  24 non-null     object
dtypes: int64(1), object(4)
memory usage: 1.1+ KB
8 có thể lấy từ điển tên cột và kiểu dữ liệu. Điều này thực sự hữu ích và tôi đã không biết điều này cho đến khi tôi viết bài báo này. Đây là cách chúng ta có thể xác định ánh xạ loại dữ liệu cột

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota', match='Election results from statewide races')
len(table_MN)
0

Đây là một gợi ý nhanh. Gõ từ điển này chậm. Sử dụng phím tắt này để xây dựng từ điển các cột có giá trị mặc định là

df['GOP'].astype('float')
0

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota', match='Election results from statewide races')
len(table_MN)
1

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota', match='Election results from statewide races')
len(table_MN)
2

Tôi cũng đã tạo một từ điển có các giá trị để thay thế

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota', match='Election results from statewide races')
len(table_MN)
3

Bây giờ chúng tôi có thể gọi thay thế trên DataFrame này, chuyển đổi sang loại mong muốn và nhận các giá trị số rõ ràng của chúng tôi

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota', match='Election results from statewide races')
len(table_MN)
4

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota', match='Election results from statewide races')
len(table_MN)
5

Hiện tại trông như thế này

Năm danh nghĩa GDP (tỷ. Mỹ -Đô la Mỹ) GDP bình quân đầu người (năm US-Dollar)GDP growth(real)Inflation rate(in percent)Unemployment (in percent)Budget balance(in % of GDP)[107]Government debt held by public(in % of GDP)[108]Current account balance(in % of GDP)0202020234.057589-5.90.6211.1NaN79.9NaN1201921439.0646742.21.803.5-4.678.9-2.52201820580.2628693.02.403.9-3.877.8-2.43201719519.4600002.32.104.4-3.476.1-2.34201618715.0578781.71.304.9-3.176.4-2.3

Để chứng minh rằng nó hoạt động, chúng tôi cũng có thể vẽ biểu đồ dữ liệu

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota', match='Election results from statewide races')
len(table_MN)
6

Làm cách nào để đọc nội dung HTML bằng Python?

Nếu bạn đang theo dõi sát sao, bạn có thể nhận thấy việc sử dụng cách gọi

df = table_MN[0]
df.head()
3 bị xiềng xích

table_MN = pd.read_html('https://en.wikipedia.org/wiki/Minnesota', match='Election results from statewide races')
len(table_MN)
7

Lý do tôi đưa nó vào đó là vì tôi không thể tìm ra cách làm sạch

df['GOP'].astype('float')
2 bằng từ điển đầu tiên
df = table_MN[0]
df.head()
3. Tôi nghĩ vấn đề là tôi không thể dự đoán thứ tự xóa dữ liệu này nên tôi quyết định thực hiện thay thế theo hai giai đoạn

Làm cách nào để lấy dữ liệu từ HTML sang Python?

Các bước để cạo bất kỳ trang web nào . Chúng ta có thể làm điều này bằng cách sử dụng thư viện Request của Python. Tìm nạp và phân tích dữ liệu bằng Beautifulsoup và duy trì dữ liệu trong một số cấu trúc dữ liệu như Dict hoặc List. Sending an HTTP GET request to the URL of the webpage that you want to scrape, which will respond with HTML content. We can do this by using the Request library of Python. Fetching and parsing the data using Beautifulsoup and maintain the data in some data structure such as Dict or List.

Làm cách nào để chuyển đổi mã HTML thành văn bản trong Python?

Nhiều khi làm việc với tự động hóa web, chúng tôi cần chuyển đổi mã HTML thành Văn bản. Điều này có thể được thực hiện bằng cách sử dụng BeautifulSoup . Mô-đun này cung cấp hàm get_text() lấy HTML làm đầu vào và trả về văn bản làm đầu ra.