Извлечение информации с веб-страницы и запись в файл .xls с использованием pandas и bs4

#python #pandas #web-scraping #beautifulsoup

#python #pandas #очистка веб-страниц #beautifulsoup

Вопрос:

Я новичок в программировании на Python. Я практикую очистку веб-страниц с использованием модуля bs4 на python.

Я извлек некоторые поля с веб-страницы, но, но пока я пытаюсь записать их в файл .xls, файл .xls остается пустым, за исключением заголовков. Пожалуйста, скажите, где я делаю неправильно, и, если возможно, предложите, что нужно сделать.

 from bs4 import BeautifulSoup as bs
import pandas as pd

res = requests.get('https://rwbj.com.au/find-an-agent.html')
soup = bs(res.content, 'lxml')

data = soup.find_all("div",{"class":"fluidgrid-cell fluidgrid-cell-2"})

records = []
name =[]
phone =[]
email=[]
title=[]
location=[]
for item in data:
    name = item.find('h3',class_='heading').text.strip()
    phone = item.find('a',class_='text text-link text-small').text.strip()
    email = item.find('a',class_='text text-link text-small')['href']
    title = item.find('div',class_='text text-small').text.strip()
    location = item.find('div',class_='text text-small').text.strip()

    records.append({'Names': name, 'Title': title, 'Email': email, 'Phone': phone, 'Location': location})

df = pd.DataFrame(records,columns=['Names','Title','Phone','Email','Location'])
df=df.drop_duplicates()
df.to_excel(r'C:UserslaptopDesktopRamp;W.xls', sheet_name='MyData2', index = False, header=True)

  

Ответ №1:

Если вы не хотите использовать selenium, то вы можете сделать тот же самый post-запрос, который делает веб-страница. Это выдаст вам xml ответ, который вы можете проанализировать, используя Beautifulsoup , чтобы получить нужный вам результат.

Мы можем использовать вкладку сеть в инструменте проверки, чтобы получить выполняемый запрос, а также данные формы для этого запроса.

введите описание изображения здесь

Далее мы должны выполнить тот же запрос, используя python-requests , и проанализировать выходные данные.

 import requests
from bs4 import BeautifulSoup
import pandas as pd
number_of_agents_required=20 # they only have 20 on the site
payload={
'act':'act_fgxml',
'15[offset]':0,
'15[perpage]':number_of_agents_required,
'require':0,
'fgpid':15,
'ajax':1
}
records=[]
r=requests.post('https://www.rwbj.com.au/find-an-agent.html',data=payload)
soup=BeautifulSoup(r.text,'lxml')
for row in soup.find_all('row'):
    name=row.find('name').text
    title=row.position.text.replace('amp;amp;','amp;')
    email=row.email.text
    phone=row.phone.text
    location=row.office.text
    records.append([name,title,email,phone,location])
df=pd.DataFrame(records,columns=['Names','Title','Phone','Email','Location'])
df.to_excel('Ramp;W.xls', sheet_name='MyData2', index = False, header=True)
  

Вывод:

введите описание изображения здесь

Комментарии:

1. Как ни странно, я не видел, чтобы это отображалось при ответе. 1 для лучшего подхода.

2. Да, это работает отлично. Пожалуйста, если вы можете объяснить мне, как работает приведенный выше код. На вкладке Элемент я не смог найти тег ‘row’. Даже причина использования ‘amp;amp’ и ‘amp;’. Будьте любезны, если вы можете объяснить свой код, поскольку я новичок в программировании на Python и хочу узнать больше об этом методе. Часть кода, если вы можете, любезно объясните : for row in soup.find_all('row'): name=row.find('name').text title=row.position.text.replace('amp;amp;','amp;') email=row.email.text phone=row.phone.text location=row.office.text

3. @ag2019 Если вы, print(soup) вы можете увидеть xml ответ. Код значит — для каждого row тега в XML, сделать текст внутри name , title , email , phone , office теги и сохранить их в переменной с левой стороны.

4. Хорошо, большое спасибо за объяснение. Здесь мы устанавливаем ‘number_of_agent’ равным 20, поскольку мы можем видеть 20 агентов на веб-сайте, но если на веб-странице намного больше агентов, для подсчета которых потребуется время, то какое значение мы присвоим переменной ‘number_of_agent’?

Ответ №2:

Вы могли бы использовать метод, подобный selenium, для обеспечения рендеринга содержимого на javascript. Затем вы можете использовать page_source для продолжения работы со своим скриптом. Я намеренно сохранил ваш скрипт и добавил только новые строки для ожидания содержимого.

Вы могли бы запустить selenium без головы или переключиться на использование HTMLSession вместо этого.

 from bs4 import BeautifulSoup as bs
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
import pandas as pd

d = webdriver.Chrome()
d.get('https://rwbj.com.au/find-an-agent.html')

WebDriverWait(d,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "h3")))

soup = bs(d.page_source, 'lxml')
d.quit()
data = soup.find_all("div",{"class":"fluidgrid-cell fluidgrid-cell-2"})

records = []
name =[]
phone =[]
email=[]
title=[]
location=[]
for item in data:
    name = item.find('h3',class_='heading').text.strip()
    phone = item.find('a',class_='text text-link text-small').text.strip()
    email = item.find('a',class_='text text-link text-small')['href']
    title = item.find('div',class_='text text-small').text.strip()
    location = item.find('div',class_='text text-small').text.strip()
    records.append({'Names': name, 'Title': title, 'Email': email, 'Phone': phone, 'Location': location})

df = pd.DataFrame(records,columns=['Names','Title','Phone','Email','Location'])
print(df)
  

Я мог бы рассмотреть, в зависимости от того, присутствовали ли все элементы для каждого пользователя, что-то вроде:

 from bs4 import BeautifulSoup as bs
from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.chrome.options import Options
import pandas as pd

options = Options()
options.headless = True

d = webdriver.Chrome(options = options) 
d.get('https://rwbj.com.au/find-an-agent.html')

WebDriverWait(d,10).until(EC.presence_of_all_elements_located((By.CSS_SELECTOR, "h3")))

soup = bs(d.page_source, 'lxml')
d.quit()
names = [item.text for item in soup.select('h3')]
titles = [item.text for item in soup.select('h3 ~ div:nth-of-type(1)')]
tels = [item.text for item in soup.select('h3   a')]
emails = [item['href'] for item in soup.select('h3 ~ a:nth-of-type(2)')]
locations = [item.text for item in soup.select('h3 ~ div:nth-of-type(2)')]      
records = list(zip(names, titles, tels, emails, positions))
df = pd.DataFrame(records,columns=['Names','Title','Phone','Email','Location'])
print(df)
  

Комментарии:

1. Хорошо, я попытаюсь изучить Selenium сейчас, но не могли бы вы, пожалуйста, сказать мне причину, по которой не разрешается извлекать информацию с веб-страницы.

2. страница обновляет содержимое с помощью запросов xhr. Вам нужно либо отправлять запросы по этому URL, либо использовать selenium, чтобы предоставить время для отображения содержимого.