Как я могу создать фрейм данных из данных, которые я скопировал с веб-сайта? - PullRequest
1 голос
/ 04 апреля 2019

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

[{'job_title': 'Junior Data Scientist', 'company': '\n \ n BBC ', summary': "\ n Сейчас мы ищем младшего ученого данных, который приедет и поработает с нашей командой по маркетингу и аудитории в Лондоне. Команда по науке о данных отвечает за разработку ...", "ссылка": 'www.jobsite.com',
'summary_text': "Введение в работу \ nПредставьте, что Netflix, The Huffington Post, ESPN и Spotify были объединены в одно .... etc

Я хочу создать фрейм данных или CSV, который выглядит следующим образом:

Expected Output

прямо сейчас, я использую этот цикл:

for page in pages:
    source = requests.get('https://www.jobsite.co.uk/jobs?q=data+scientist&start='.format()).text
    soup = BeautifulSoup(source, 'lxml')

results = []
for jobs in soup.findAll(class_='result'):
    result = {
                'job_title': '',
                'company': '',
                'summary': '',
                'link': '',
                'summary_text': ''
            }

и после использования цикла я просто распечатываю результаты.

Какой хороший способ получить вывод в кадре данных? Спасибо!

Ответы [ 2 ]

3 голосов
/ 04 апреля 2019

Посмотрите на API DataFrame для панд . Существует несколько способов инициализации фрейма данных

  • список словарей
  • список списков

Вам просто нужно добавить список или словарь в глобальную переменную, и вы должны быть в порядке.

results = []
for page in pages:

      source = requests.get('https://www.jobsite.co.uk/jobs?q=data+scientist&start='.format()).text
      soup = BeautifulSoup(source, 'lxml')


      for jobs in soup.findAll(class_='result'):
          result = {
                'job_title': '', # assuming this has value like you shared in the example in your question
                'company': '',
                'summary': '',
                'link': '',
                'summary_text': ''
            }
           results.append(result)
      # results is now a list of dictionaries
df= pandas.DataFrame(results)

Еще одно предложение, не думайте о том, чтобы записать это в кадр данных в той же программе. Сначала скопируйте все ваши HTML-файлы в папку, а затем снова проанализируйте их. Таким образом, если вам нужна дополнительная информация со страницы, которую вы не рассматривали ранее, или если программа закрывается из-за какой-то ошибки синтаксического анализа или тайм-аута, работа не теряется. Держите разбор отдельно от логики сканирования.

1 голос
/ 04 апреля 2019

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

Правильно ли выбран ваш класс result?Вы также можете использовать for job in soup.select('.job'):.Затем вам нужно определить соответствующие селекторы для заполнения значений.Я думаю, что проще получить все ссылки на вакансии для каждой страницы, а затем посетить страницу и извлечь значения из строки, подобной json, на странице.Добавьте Session для повторного использования соединения.

Для предотвращения блокировки требуется явное ожидание

import requests 
from bs4 import BeautifulSoup as bs
import json
import pandas as pd
import time

headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'}
results = []
links = []
pages = 3

with requests.Session() as s:
    for page in range(1, pages + 1):
        try:
            url = 'https://www.jobsite.co.uk/jobs?q=data+scientist&start=1&page={}'.format(page)
            source = s.get(url, headers = headers).text
            soup = bs(source, 'lxml') 
            links.append([link['href'] for link in soup.select('.job-title a')])
        except Exception as e:
            print(e, url )
        finally:
            time.sleep(2)

    final_list = [item for sublist in links for item in sublist]  

    for link in final_list:  
        source = s.get(link, headers = headers).text        
        soup = bs(source, 'lxml')
        data = soup.select_one('#jobPostingSchema').text #json like string containing all info
        item = json.loads(data)

        result = {
        'Title' : item['title'],
         'Company' : item['hiringOrganization']['name'],
         'Url' : link,
         'Summary' :bs(item['description'],'lxml').text
    }

        results.append(result)
        time.sleep(1)
df = pd.DataFrame(results, columns = ['Title', 'Company', 'Url', 'Summary']) 
print(df)
df.to_csv(r'C:\Users\User\Desktop\data.csv', sep=',', encoding='utf-8-sig',index = False )

Пример результатов:

enter image description here


Не могу представить, что вам нужны все страницы, но вы можете использовать что-то похожее на:

import requests 
from bs4 import BeautifulSoup as bs
import json
import pandas as pd
import time

headers = { 'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/60.0.3112.113 Safari/537.36'}
results = []
links = []
pages = 0

def get_links(url, page):
    try:
        source = s.get(url, headers = headers).text
        soup = bs(source, 'lxml') 
        page_links = [link['href'] for link in soup.select('.job-title a')]
        if page == 1:
            global pages
            pages = int(soup.select_one('.page-title span').text.replace(',',''))
    except Exception as e:
        print(e, url )
    finally:
        time.sleep(1)
    return page_links

with requests.Session() as s:

    links.append(get_links('https://www.jobsite.co.uk/jobs?q=data+scientist&start=1&page=1',1))

    for page in range(2, pages + 1):
        url = 'https://www.jobsite.co.uk/jobs?q=data+scientist&start=1&page={}'.format(page)
        links.append(get_links(url, page))

    final_list = [item for sublist in links for item in sublist]  

    for link in final_list:  
        source = s.get(link, headers = headers).text        
        soup = bs(source, 'lxml')
        data = soup.select_one('#jobPostingSchema').text #json like string containing all info
        item = json.loads(data)

        result = {
        'Title' : item['title'],
         'Company' : item['hiringOrganization']['name'],
         'Url' : link,
         'Summary' :bs(item['description'],'lxml').text
    }

        results.append(result)
        time.sleep(1)
df = pd.DataFrame(results, columns = ['Title', 'Company', 'Url', 'Summary']) 
print(df)
df.to_csv(r'C:\Users\User\Desktop\data.csv', sep=',', encoding='utf-8-sig',index = False )
...