Использование веб-драйвера в BeautifulSoup для очистки веб-страниц - PullRequest
0 голосов
/ 16 января 2020

Я пытаюсь сделать пагинацию с использованием BeautifulSoup, поэтому я использовал веб-драйвер для разбивки на другие страницы. Однако я не совсем уверен, есть ли другой способ получить контент с динамической c веб-страницы с помощью веб-драйвера и сопоставить его с моим кодом. Ниже приведен полный код, который я пытался реализовать, но веб-драйвер не работает. Сеть, которую я собираюсь почистить, [ссылка здесь] [1]

for i in range(1, MAX_PAGE_NUM + 1):
    page_num = (MAX_PAGE_DIG - len(str(i))) * "0" + str(i)
    raw = requests.get('').text

driver.get(raw)

raw = raw.replace("</br>", "")

soup = BeautifulSoup(raw, 'html.parser')

name = soup.find_all('div', {'class' :'cbp-vm-companytext'})
phone = [re.findall('\>.*?<',d.find('span')['data-content'])[0][1:][:-1] for d in soup.find_all('div',{'class':'cbp-vm-cta'})]
addresses = [x.text.strip().split("\r\n")[-1].strip() for x in soup.find_all("div", class_='cbp-vm-address')]

print(addresses)
print(name)

num_page_items = len(addresses)
with open('results.csv', 'a') as f:
    for i in range(num_page_items):
        f.write(name[i].text + "," + phone[i] + "," + addresses[i] + "," +  "\n")

Конечно, я ошибочно добавляю веб-драйвер в код. Что я должен исправить, чтобы веб-драйвер работал?

1 Ответ

1 голос
/ 16 января 2020

Если вы используете Selenium для чтения страницы, то вы также можете использовать Selenium для поиска элементов на странице.

Некоторые элементы не имеют companytext, поэтому, если вы получаете отдельно companytext и Отдельно address / phone тогда вы можете создать неправильные пары: (second name, first phone, first address), (third name, second phone, second address), et c. Лучше найти элемент, который группирует name, phone, address, а затем искать name, phone, address внутри этого элемента - если он не может найти имя, тогда вы должны поставить пустое имя или выполнить поиск другой элемент с именем внутри этой группы. Я обнаружил, что некоторые элементы отображают изображение с lo go вместо имени и имеют имя в <img alt="...">

Не очень хорошая идея записывать данные CSV в файл, используя стандарт write(), потому что address может иметь много ,, и это может создать много столбцов. При использовании модуля csv адрес будет помещен в " " в виде одного столбца.

from selenium import webdriver
import csv

MAX_PAGE_NUM = 5

#driver = webdriver.Chrome()
driver = webdriver.Firefox()

with open('results.csv', 'w') as f:
    csv_writer = csv.writer(f)
    csv_writer.writerow(["Bussiness Name", "Phone Number", "Address"])

    for page_num in range(1, MAX_PAGE_NUM+1):
        #page_num = '{:03}'.format(page_num)
        url = 'https://www.yellowpages.my/listing/results.php?keyword=boutique&where=selangor&screen={}'.format(page_num)
        driver.get(url)
        for item in driver.find_elements_by_xpath('//div[@id="content_listView"]//li'):
            try:
                name = item.find_element_by_xpath('.//div[@class="cbp-vm-companytext"]').text
            except Exception as ex:
                #print('ex:', ex)
                name = item.find_element_by_xpath('.//a[@class="cbp-vm-image"]/img').get_attribute('alt')

            phone = item.find_element_by_xpath('.//div[@class="cbp-vm-cta"]//span[@data-original-title="Phone"]').get_attribute('data-content')
            phone = phone[:-4].split(">")[-1]

            address = item.find_element_by_xpath('.//div[@class="cbp-vm-address"]').text
            address = address.split('\n')[-1]

            print(name, '|', phone, '|', address)
            csv_writer.writerow([name, phone, address])

Кстати: вам не нужно преобразовывать номер страницы в три цифры - ie. 001 - работает также с 1. Но если вы хотите конвертировать, используйте форматирование строки

page_num = '{:03}'.format(i)

Это можно сделать также только с requests и BeautifulSoup без Selenium.

Если у вас есть чтобы получить HTML из Selenium, тогда у вас есть driver.page_source - но driver.get() нужно url, и тогда вам не нужно requests для этого.

driver.get(url)
html = driver.page_source
soup = BeautifulSoup(html, 'html.parser')

РЕДАКТИРОВАТЬ: Я могу получить его с requests и BeautifulSoup без Selenium, только если я использую "lxml" вместо "html.parser". Кажется, в HTML есть некоторые ошибки, и "html.parser" имеет проблему, чтобы правильно разобрать его

import requests
from bs4 import BeautifulSoup as BS
import csv
#import webbrowser

MAX_PAGE_NUM = 5

#headers = {
#  "User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:74.0) Gecko/20100101 Firefox/74.0"
#}

with open('results.csv', 'w') as f:
    csv_writer = csv.writer(f)
    csv_writer.writerow(["Bussiness Name", "Phone Number", "Address"])

    for page_num in range(1, MAX_PAGE_NUM+1):
        #page_num = '{:03}'.format(page_num)
        url = 'https://www.yellowpages.my/listing/results.php?keyword=boutique&where=selangor&screen={}'.format(page_num)

        response = requests.get(url) #, headers=headers)
        soup = BS(response.text, 'lxml')
        #soup = BS(response.text, 'html.parser')

        #with open('temp.html', 'w') as fh:
        #    fh.write(response.text)
        #webbrowser.open('temp.html')

        #all_items = soup.find('div', {'id': 'content_listView'}).find_all('li')
        #print('len:', len(all_items))

        #for item in all_items:
        for item in soup.find('div', {'id': 'content_listView'}).find_all('li'):
            try:
                name = item.find('div', {'class': 'cbp-vm-companytext'}).text
            except Exception as ex:
                #print('ex:', ex)
                name = item.find('a', {'class': 'cbp-vm-image'}).find('img')['alt']

            phone = item.find('div', {'class': 'cbp-vm-cta'}).find('span', {'data-original-title': 'Phone'})['data-content']
            phone = phone[:-4].split(">")[-1].strip()

            address = item.find('div', {'class': 'cbp-vm-address'}).text
            address = address.split('\n')[-1].strip()

            print(name, '|', phone, '|', address)
            csv_writer.writerow([name, phone, address])
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...