2017-02-18 8 views
2

Я пытался очистить таблицу от here, но мне кажется, что BeautifulSoup не находит никакой таблицы.Скребок таблицы со страницы с использованием beautifulsoup, таблица не найдена

я писал:

import requests 
import pandas as pd 
from bs4 import BeautifulSoup 
import csv 

url = "http://www.payscale.com/college-salary-report/bachelors?page=65" 
r=requests.get(url) 
data=r.text 

soup=BeautifulSoup(data,'xml') 
table=soup.find_all('table') 
print table #prints nothing.. 

на основе других подобных вопросов, я полагаю, что HTML сломана некоторым образом, но я не эксперт .. не удалось найти ответ на эти: (Beautiful soup missing some html table tags), (Extracting a table from a website), (Scraping a table using BeautifulSoup), или даже (Python+BeautifulSoup: scraping a particular table from a webpage)

Благодаря кучу!

+0

Я бы напечатать 'data' и посмотреть, если вы найдете таблицу в пределах этой страницы. – metame

+0

Спасибо @metama. Я сделал это - единственное: и bsoup не нашли бы его. Также - если поиск в этом случае не так, то как бы вы шли Это? благодаря! – oba2311

+0

на странице нет тега таблицы. Вся информация таблицы содержится в теге скрипта. –

ответ

1

Вы анализируете html, но вы использовали парсер xml.
Вы должны использовать soup=BeautifulSoup(data,"html.parser")
Ваши данные указаны в поле script, на самом деле нет table. Итак, вам нужно найти тексты внутри script.
N.B: Если вы используете Python 2.x, используйте «HTMLParser» вместо «html.parser».

Вот код.

import csv 
import requests 
from bs4 import BeautifulSoup 

url = "http://www.payscale.com/college-salary-report/bachelors?page=65" 
r=requests.get(url) 
data=r.text 

soup=BeautifulSoup(data,"html.parser") 
scripts = soup.find_all("script") 

file_name = open("table.csv","w",newline="") 
writer = csv.writer(file_name) 
list_to_write = [] 

list_to_write.append(["Rank","School Name","School Type","Early Career Median Pay","Mid-Career Median Pay","% High Job Meaning","% STEM"]) 

for script in scripts: 
    text = script.text 
    start = 0 
    end = 0 
    if(len(text) > 10000): 
     while(start > -1): 
      start = text.find('"School Name":"',start) 
      if(start == -1): 
       break 
      start += len('"School Name":"') 
      end = text.find('"',start) 
      school_name = text[start:end] 

      start = text.find('"Early Career Median Pay":"',start) 
      start += len('"Early Career Median Pay":"') 
      end = text.find('"',start) 
      early_pay = text[start:end] 

      start = text.find('"Mid-Career Median Pay":"',start) 
      start += len('"Mid-Career Median Pay":"') 
      end = text.find('"',start) 
      mid_pay = text[start:end] 

      start = text.find('"Rank":"',start) 
      start += len('"Rank":"') 
      end = text.find('"',start) 
      rank = text[start:end] 

      start = text.find('"% High Job Meaning":"',start) 
      start += len('"% High Job Meaning":"') 
      end = text.find('"',start) 
      high_job = text[start:end] 

      start = text.find('"School Type":"',start) 
      start += len('"School Type":"') 
      end = text.find('"',start) 
      school_type = text[start:end] 

      start = text.find('"% STEM":"',start) 
      start += len('"% STEM":"') 
      end = text.find('"',start) 
      stem = text[start:end] 

      list_to_write.append([rank,school_name,school_type,early_pay,mid_pay,high_job,stem]) 
writer.writerows(list_to_write) 
file_name.close() 

Это создаст необходимую таблицу в csv. Не забудьте закрыть файл, когда закончите.

+0

** Спасибо ** @Khairul Ваш код (почти) работает. Мне пришлось удалить _newline = "" _, потому что python утверждает, что он не примет этот параметр в функцию _open() _. Когда я посмотрел, чтобы узнать это, я увидел, что это новый параметр, введенный для python 3. Я говорю об этой строке: 'file_name = open (" table.csv "," w ", newline = "") ' Это очень полезно -> спасибо. – oba2311

+1

Я закодирован в python 3.5 и жалею, что не знал, что это новый параметр в python 3, иначе я бы упомянул. @ oba2311 –

+1

Не беспокойтесь, @Hhairul вы действительно решили проблему! поэтому проверка - спасибо. – oba2311

2

Хотя это не будет найти таблицу, которого нет в r.text, вы просите BeautifulSoup использовать xml анализатор вместо html.parser, поэтому я бы рекомендовал изменить это строку:

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

Один из проблемы, с которыми вы столкнетесь в веб-скребке, - это так называемые «клиент-рендеринговые» веб-сайты или серверы. В основном это означает, что страница, которую вы получите из базового html-запроса через модуль requests или через curl, например, представляет собой не тот контент, который будет отображаться в веб-браузере. Некоторые из общих рамок для этого - Реакция и Угловая. Если вы изучите источник страницы, которую вы хотите очистить, у них есть data-react-id s на нескольких своих элементах html. Общим признаком для угловых страниц являются аналогичные атрибуты элементов с префиксом ng, например. ng-if или ng-bind. Вы можете увидеть источник страницы в браузере Chrome или Firefox через соответствующие средства разработки, которые можно запустить с помощью сочетания клавиш Ctrl+Shift+I в любом браузере. Стоит отметить, что не все React & Угловые страницы обрабатываются только клиентом.

Для того, чтобы получить такой контент, вам понадобится использовать браузер без браузера, например Selenium. Есть много ресурсов на веб-соскабливание с Selenium и Python.

2

Данные находятся в переменной JavaScript, вы должны найти текстовые данные js, а затем использовать regex для ее извлечения. когда вы получаете данные, это объект списка json, который содержит 900+ school dict, вы должны использовать модуль json, чтобы загрузить его в список python obejct.

import requests, bs4, re, json 

url = "http://www.payscale.com/college-salary-report/bachelors?page=65" 
r = requests.get(url) 
data = r.text 
soup = bs4.BeautifulSoup(data, 'lxml') 
var = soup.find(text=re.compile('collegeSalaryReportData')) 
table_text = re.search(r'collegeSalaryReportData = (\[.+\]);\n var', var, re.DOTALL).group(1) 
table_data = json.loads(table_text) 
pprint(table_data) 
print('The number of school', len(table_data)) 

из:

{'% Female': '0.57', 
    '% High Job Meaning': 'N/A', 
    '% Male': '0.43', 
    '% Pell': 'N/A', 
    '% STEM': '0.1', 
    '% who Recommend School': 'N/A', 
    'Division 1 Basketball Classifications': 'Not Division 1 Basketball', 
    'Division 1 Football Classifications': 'Not Division 1 Football', 
    'Early Career Median Pay': '36200', 
    'IPEDS ID': '199643', 
    'ImageUrl': '/content/school_logos/Shaw University_50px.png', 
    'Mid-Career Median Pay': '45600', 
    'Rank': '963', 
    'School Name': 'Shaw University', 
    'School Sector': 'Private not-for-profit', 
    'School Type': 'Private School, Religious', 
    'State': 'North Carolina', 
    'Undergraduate Enrollment': '1664', 
    'Url': '/research/US/School=Shaw_University/Salary', 
    'Zip Code': '27601'}] 
The number of school 963