【问题标题】:How can I create a dataframe from data I scraped from a website?如何根据从网站上抓取的数据创建数据框?
【发布时间】:2019-08-25 18:22:20
【问题描述】:

我正在尝试从职位发布数据中抓取网站,输出如下所示:

[{'job_title': '初级数据科学家','company': '\n\n BBC', summary': "\n 我们现在正在寻找一名初级数据科学家 来与我们在伦敦的营销和受众团队合作。数据 科学团队负责设计...", 'link': 'www.jobsite.com',
'summary_text': "职位介绍\n想象一下,如果 Netflix、赫芬顿邮报、ESPN 和 Spotify 合二为一……等等

我想创建一个如下所示的数据框或 CSV:

现在,这是我正在使用的循环:

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': ''
            }

使用循环后,我只打印结果。

在数据框中获取输出的好方法是什么?谢谢!

【问题讨论】:

    标签: python pandas for-loop web-scraping export-to-csv


    【解决方案1】:

    我认为您需要定义页数并将其添加到您的网址中(确保您有一个占位符来表示我认为您的代码和其他答案都没有的值)。我通过扩展您的 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 )
    

    结果示例:


    我无法想象你想要所有页面,但你可以使用类似于:

    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 )
    

    【讨论】:

    • 我试过你的第一个答案,效果很好。该类之前不正确,因为我正在解析一个不同的工作站点并将“jobsite.co.uk”写为占位符,不知道它是一个实际站点。我确实有页面的占位符,我只是在我的帖子中错过了那行代码。你能解释一下什么是重用会话吗?我以前没有使用过会话。
    • docs.python-requests.org/en/master/user/advanced/… 因此,如果您向同一主机发出多个请求,则会重用底层 TCP 连接,从而显着提高性能
    【解决方案2】:

    查看pandas Dataframe API。有几种方法可以初始化数据框

    • 词典列表
    • 列表列表

    您只需要将列表或字典附加到全局变量,就可以了。

    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 文件转储到一个文件夹中,然后再次解析它们。这样,如果您需要从以前没有考虑过的页面中获取更多信息,或者如果程序由于某些解析错误或超时而终止,则工作不会丢失。将解析与爬取逻辑分开。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-17
      • 2013-03-14
      • 2013-05-21
      • 1970-01-01
      • 2019-04-02
      相关资源
      最近更新 更多