Красивый суп — получение текста с нескольких страниц

#python #beautifulsoup

#python #beautifulsoup

Вопрос:

Я хочу очистить следующую страницу:http://www.interzum.com/exhibitors-and-products/exhibitor-index/exhibitor-index-15.php

Я хочу просмотреть каждую из ссылок экспонента и получить контактные данные. Затем мне нужно сделать это на всех 77 страницах.

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

Это то, что у меня пока есть в записной книжке jupyter:

 from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
import time
import pandas as pd
import requests
from bs4 import BeautifulSoup

url = 'http://www.interzum.com/exhibitors-and-products/exhibitor-index/exhibitor-index-15.php'
text = requests.get(url).text
page1 = BeautifulSoup(text, "html.parser")

def get_data(url):
    text = requests.get(url).text
    page2 = BeautifulSoup(text, "html.parser")

    title = page2.find('h1', attrs={'class':'hl_2'}).getText()    
    content = page2.find('div', attrs={'class':'content'}).getText()
    phone = page2.find('div', attrs={'class':'sico ico_phone'}).getText()
    email = page2.find('a', attrs={'class':'sico ico_email'}).getText
    webpage = page2.find('a', attrs={'class':'sico ico_link'}).getText


    data = {'Name': [title],
          'Address': [content],
          'Phone number': [phone],
          'Email': [email],
          'Web': [web]            
         } 

df = pd.DataFrame()
for a in page1.findAll('a', attrs={'class':'initial_noline'}):
    df2 = get_data(a['href'])
    df = pd.concat([df, df2])



AttributeError: 'NoneType' object has no attribute 'getText'
  

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

Какова рекомендуемая структура для этого?

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

1. Пожалуйста, поделитесь полным сообщением об ошибке.

2. Ваша функция ничего не возвращает. Вы должны закончить его чем-то вроде return data

3. пара ошибок в коде: вы ищете ‘a’ для электронной почты и веб-страницы, они находятся в divs. В одном месте у вас есть веб, а в другом — веб-страница. URL-это не полный URL-адрес, вам нужно добавить свой домен, подобный get_data('http://www.interzum.com' a['href']) . Наконец, не все ссылки являются допустимыми. В тех, которые вам нужны, есть kid = некоторый идентификатор. Чтобы фильтровать только эти ссылки, используйте if 'kid=' not in a['href'] : continue . Перед помещением вашей функции в def убедитесь, что она работает с одним образцом, а затем используйте ее как функцию.

Ответ №1:

Вот несколько отлаженная версия.

 import pandas as pd
import requests
from bs4 import BeautifulSoup

url = 'http://www.interzum.com/exhibitors-and-products/exhibitor-index/exhibitor-index-15.php'
text = requests.get(url).text
page1 = BeautifulSoup(text, "html.parser")

def get_data(url):
    text = requests.get(url).text
    page2 = BeautifulSoup(text, "html.parser")

    title = page2.find('h1', attrs={'class':'hl_2'}).getText()    
    content = page2.find('div', attrs={'class':'content'}).getText()
    phone = page2.find('div', attrs={'class':'sico ico_phone'}).getText()
    email = page2.find('div', attrs={'class':'sico ico_email'}).getText
    webpage = page2.find('div', attrs={'class':'sico ico_link'}).getText


    data = [[title, content,phone, email, webpage]] 
    return data

df = pd.DataFrame()
for a in page1.findAll('a', attrs={'class':'initial_noline'}):
    if 'kid=' not in a['href'] : continue
    print('http://www.interzum.com'   a['href'])
    data = get_data('http://www.interzum.com'   a['href'])
    df.append(data)
  

Ответ №2:

Ваш код поочередно вызывает функцию getText (.getText()) и обращается к атрибуту getText (.getText) по возвращаемому значению, которое может быть none.

 python
>>> a = None
>>> type(a)
<type 'NoneType'>
>>> a.foo()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'foo'
>>> a.foo
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'NoneType' object has no attribute 'foo'
>>> 
  

Просмотрите документы BeautifulSoup и определите, что .find() возвращает и как правильно получить доступ к проанализированным данным внутри.

Ответ №3:

Мне удалось получить почти все, что мне нужно. Мой код следующий:

 import pandas as pd
import requests
from bs4 import BeautifulSoup
from selenium import webdriver
from selenium.webdriver.common.desired_capabilities import DesiredCapabilities
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary
from selenium.webdriver.common.keys import Keys
from selenium.common.exceptions import NoSuchElementException
import time

binary = FirefoxBinary('geckodriver.exe')
driver = webdriver.Firefox()
driver.get('http://www.interzum.com/exhibitors-and-products/exhibitor-        index/exhibitor-index-15.php')

url = 'http://www.interzum.com/exhibitors-and-products/exhibitor-index/exhibitor-index-15.php'
text = requests.get(url).text
page1 = BeautifulSoup(text, "html.parser")

def get_data(url, tries=0, max_tries=3):
    text_test2 = requests.get(url).text
    page2 = BeautifulSoup(text_test2, "html.parser")

    try:
        title = page2.find('h1', attrs={'class':'hl_2'}).text    
        content = page2.find('div', attrs={'class':'cont'}).text
        phone = page2.find('div', attrs={'class':'sico ico_phone'}).text
        email_div = page2.find('div', attrs={'class':'sico ico_email'})
        email = email_div.find('a', attrs={'class': 'xsecondarylink'})['href']
    
    
       if page2.find_all("div", {"class": "sico ico_link"}):
            web_div = page2.find('div', attrs={'class':'sico ico_link'})
            web = web_div.find('a', attrs={'class':'xsecondarylink'})['href']

    except:
        if tries < max_tries:
            tries  = 1
            print("try {}".format(tries))
            return get_data(url, tries)
    

    data = {'Name': [title],
            'Street address': [content], 
            'Phone number': [phone],
            'Email': [email],
            'Web': [web]            
            }
    
    return pd.DataFrame(data=data)


df = pd.DataFrame()
for i in range(0,80):
    print(i)
    page1 = BeautifulSoup(driver.page_source, 'html.parser')


    for div in page1.findAll('div', attrs={'class':'item'}):

        for a in div.findAll('a', attrs={'class':'initial_noline'}):
            if 'kid=' not in a['href'] : continue
            print('http://www.interzum.com'   a['href'])

            data = get_data('http://www.interzum.com'   a['href'])
            df = pd.concat([df, data])
        
    next_button = driver.find_element_by_class_name('slick-next')
    next_button.click()
    time.sleep(20)

df.to_csv('result.csv')
  

Этот код работает до тех пор, пока не перейдет ко второй ссылке на второй странице.