[英]Web Scraping - Extract list of text from multiple pages
我想從網站的多個頁面中提取名稱列表。 該網站有 200 多頁,我想將所有名稱保存到文本文件中。 我寫了一些代碼,但它給了我索引錯誤。
代碼:
import requests
from bs4 import BeautifulSoup as bs
URL = 'https://hamariweb.com/names/muslim/boy/page-'
#for page in range(1, 203):
page = 1
req = requests.get(URL + str(page))
soup = bs(req.text, 'html.parser')
row = soup.find('div', attrs={'class', 'row'})
books = row.find_all('a')
for book in books:
data = book.find_all('b')[0].get_text()
print(data)
輸出:
Aabbaz
Aabid
Aabideen
Aabinus
Aadam
Aadeel
Aadil
Aadroop
Aafandi
Aafaq
Aaki
Aakif
Aalah
Aalam
Aalamgeer
Aalif
Traceback (most recent call last):
File "C:\Users\Mujtaba\Documents\names.py", line 15, in <module>
data = book.find_all('b')[0].get_text()
IndexError: list index out of range
>>>
我建議將您的解析器更改為html5lib
#pip install html5lib
。 我只是覺得這樣更好。 其次,最好不要直接從您的湯對象中執行.find()
,因為它可能會導致標簽和類可能有重復的一些問題。 因此,您可能會在 html 標簽上查找數據,而您的數據甚至不在那里。 因此,最好檢查所有內容並檢查元素您想要獲取的標簽,並查看它們可能位於哪些代碼block
中,因為這樣更容易抓取,也可以避免更多錯誤。
我做了什么有我第一次檢查的元素,並找到你想要得到你的數據的代碼塊,我發現它是一個div
和它的類是mb-40 content-box
是你在哪里,所有的名字試圖得到。 幸運的是,這個類是唯一的,沒有其他元素具有same tag and class
所以我們可以直接.find()
它。
那么trs
的值只是該block
內的tr
標簽
(還要注意那些<tr>
標簽在<table>
標簽內,但好消息是那些是唯一存在的<tr>
標簽,所以不會有太多問題,比如如果會有另一個<table>
標簽具有相同的class
值)
<tr>
標簽包含您想要獲取的名稱。 您可能會問為什么有[1:]
是因為從index 1
開始不包括網站上表格中的標題。
然后只需遍歷那些tr
標簽並獲取文本。 關於為什么會發生的錯誤,這僅僅是因為index out of range
您試圖訪問index out of range
的.find_all()
結果列表項,如果沒有此類數據,則可能會發生這種情況正在發現並且如果您直接對您的soup
變量執行.find()
函數也可能發生這種情況,因為有時會有tags
並且它們各自的class
值相同但是! 里面有不同的內容。 因此,發生的情況是您希望抓取網站的特定部分,但實際發生的是您抓取了不同的部分,這就是為什么您可能無法獲得任何數據並想知道為什么會發生這種情況。
import requests
from bs4 import BeautifulSoup as bs
URL = 'https://hamariweb.com/names/muslim/boy/page-'
#for page in range(1, 203):
page = 1
req = requests.get(URL + str(page))
soup = bs(req.content, 'html5lib')
div_container = soup.find('div', class_='mb-40 content-box')
trs = div_container.find_all("tr",class_="bottom-divider")[1:]
for tr in trs:
text = tr.find("td").find("a").text
print(text)
您遇到的 IndexError 問題意味着在這種情況下,您找到的 b-tag 不包含您要查找的信息。
您可以簡單地將那段代碼包裝在 try-except 子句中。
for book in books:
try:
data = book.find_all('b')[0].get_text()
print(data)
# Add data to the all_titles list
all_titles.append(data)
except IndexError:
pass # There was no element available
這將捕獲您的錯誤並繼續前進。 但不要破壞代碼。
下面我還添加了一些額外的行來將您的標題保存到文本文件中。 看看內聯評論。
import requests
from bs4 import BeautifulSoup as bs
URL = 'https://hamariweb.com/names/muslim/boy/page-'
# Theres is where your titles will be saved. Changes as needed
PATH = '/tmp/title_file.txt'
page = 1
req = requests.get(URL + str(page))
soup = bs(req.text, 'html.parser')
row = soup.find('div', attrs={'class', 'row'})
books = row.find_all('a')
# Here your title will be stored before writing to file
all_titles = []
for book in books:
try:
# Add strip() to cleanup the input
data = book.find_all('b')[0].get_text().strip()
print(data)
# Add data to the all_titles list
all_titles.append(data)
except IndexError:
pass # There was no element available
# Open path to write
with open(PATH, 'w') as f:
# Write all titles on a new line
f.write('\n'.join(all_titles))
出現錯誤的原因是找不到<b>
標簽。
嘗試使用以下代碼來請求每個頁面並將數據保存到文件中:
import requests
from bs4 import BeautifulSoup as bs
MAIN_URL = "https://hamariweb.com/names/muslim/boy/"
URL = "https://hamariweb.com/names/muslim/boy/page-{}"
with open("output.txt", "a", encoding="utf-8") as f:
for page in range(203):
if page == 0:
req = requests.get(MAIN_URL.format(page))
else:
req = requests.get(URL.format(page))
soup = bs(req.text, "html.parser")
print(f"page # {page}, Getting: {req.url}")
book_name = (
tag.get_text(strip=True)
for tag in soup.select(
"tr.bottom-divider:nth-of-type(n+2) td:nth-of-type(1)"
)
)
f.seek(0)
f.write("\n".join(book_name) + "\n")
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.