Git Product home page Git Product logo

python3-linkedin's Introduction

Python3-LinkedIn

LinkedIn Build Status PyPI version

Python interface to the LinkedIn API

This library provides a pure Python interface to the LinkedIn Profile, Group, Company, Jobs, Search, Share, Network and Invitation REST APIs.

LinkedIn provides a service that lets people bring their LinkedIn profiles and networks with them to your site or application via their OAuth based API. This library provides a lightweight interface over a complicated LinkedIn OAuth based API to make it for python programmers easy to use.

Contributing guidelines

Please have a look to the Contributing Guidelines first.

We follow the "fork-and-pull" Git workflow.

  1. Fork the repo on GitHub
  2. Clone the project to your own machine
  3. Commit changes to your own branch
  4. Push your work back up to your fork
  5. Submit a Pull request so that we can review your changes

NOTE: Be sure to merge the latest from "upstream" before making a pull request!

Acknowledgement

Maintainer : Jonathan Dekhtiar

Contributors:

Installation

Available with the Python Package Index: https://pypi.python.org/pypi/python3-linkedin

pip install python3-linkedin

If prefered, the library can be compiled with following commands:

## First clone the repository
git clone https://github.com/DEKHTIARJonathan/python3-linkedin.git

## Then install the library
python setup.py install

Authentication

The LinkedIn REST API now supports the OAuth 2.0 protocol for authentication. This package provides a full OAuth 2.0 implementation for connecting to LinkedIn as well as an option for using an OAuth 1.0a flow that can be helpful for development purposes or just accessing your own data.

HTTP API example

Please declare and setup a new application on the LinkedIn Developer Console. Note your Client ID and Client secret. Configure it to redirect to http://localhost:8080/code/ (or to whatever local URL you decide, as long as you change it in all examples as well).

Set Client ID and Client secret in examples/http_api.py, then execute:

  1. python http_api.py
  2. Visit http://localhost:8080 in your browser, curl or similar
  3. A tab in your browser will open up
  4. You'll then be presented with a list of available routes, hit any

Developer Authentication

To connect to LinkedIn as a developer or just to access your own data, you don't even have to implement an OAuth 2.0 flow that involves redirects. You can simply use the 4 credentials that are provided to you in your LinkedIn appliation as part of an OAuth 1.0a flow and immediately access your data. Here's how:

from linkedin import linkedin

# Define CONSUMER_KEY, CONSUMER_SECRET,
# USER_TOKEN, and USER_SECRET from the credentials
# provided in your LinkedIn application

# Instantiate the developer authentication class

authentication = linkedin.LinkedInDeveloperAuthentication(
                    CONSUMER_KEY,
                    CONSUMER_SECRET,
                    USER_TOKEN,
                    USER_SECRET,
                    RETURN_URL,
                    linkedin.PERMISSIONS.enums.values()
                )

# Optionally one can send custom "state" value that will be returned from OAuth server
# It can be used to track your user state or something else (it's up to you)
# Be aware that this value is sent to OAuth server AS IS - make sure to encode or hash it

# authorization.state = 'your_encoded_message'

# Pass it in to the app...

application = linkedin.LinkedInApplication(authentication)

# Use the app....

application.get_profile()

Production Authentication

You may want to read the LinkedIn documentation about the OAuth2 authentication process first.

An example is available in examples/oauth2_authentication.py. Edit it to set your own Client ID and Client secret (get them from your LinkedIn Developer Console), and execute it. It will print a URL pointing to LinkedIn that you can open in your browser. Once the page opens, you'll be able to tell LinkedIn to grant your application access to your LinkedIn profile. LinkedIn will then redirect you to the Redirect URL you defined in your developer console. If no server is listening yet, your browser will display an error. You'll however be able to extract the authentication_code from its location bar:

"http://localhost:8080/code/?code=#############################################&state=########################"

The access token can then be retrieved from this authentication_code with the script available in examples/oauth2_code2accesstoken.py. Edit it with your Client ID and Client secret, as well as you authentication_code. Run it to print your access token.

After you get the access token, you are now permitted to make API calls on behalf of the user who granted access to you app. In addition to that, in order to prevent from going through the OAuth flow for every consecutive request, one can directly assign the access token obtained before to the application instance.

from linkedin import linkedin

application = linkedin.LinkedInApplication(token='###################################')

Quick Usage From Python Interpreter

For testing the library using an interpreter, you can benefit from the test server.

from linkedin import server
application = server.quick_api(KEY, SECRET)

This will print the authorization url to the screen. Go into that URL using a browser to grant access to the application. After you do so, the method will return with an API object you can now use.

Profile API

The Profile API returns a member's LinkedIn profile. You can use this call to return one of two versions of a user's profile which are public profile and standard profile. For more information, check out the documentation.

application.get_profile()
{u'firstName': u'ozgur',
 u'headline': u'This is my headline',
 u'lastName': u'vatansever',
 u'siteStandardProfileRequest': {u'url': u'https://www.linkedin.com/profile/view?id=46113651&authType=name&authToken=Egbj&trk=api*a101945*s101945*'}}

There are many field selectors that enable the client fetch more information from the API. All of them used by each API are listed here.

application.get_profile(selectors=['id', 'first-name', 'last-name', 'location', 'distance', 'num-connections', 'skills', 'educations'])
{u'distance': 0,
 u'educations': {u'_total': 1,
  u'values': [{u'activities': u'This is my activity and society field',
    u'degree': u'graduate',
    u'endDate': {u'year': 2009},
    u'fieldOfStudy': u'computer science',
    u'id': 42611838,
    u'notes': u'This is my additional notes field',
    u'schoolName': u'\u0130stanbul Bilgi \xdcniversitesi',
    u'startDate': {u'year': 2004}}]},
 u'firstName': u'ozgur',
 u'id': u'COjFALsKDP',
 u'lastName': u'vatansever',
 u'location': {u'country': {u'code': u'tr'}, u'name': u'Istanbul, Turkey'},
 u'numConnections': 13}

Connections API

The Connections API returns a list of 1st degree connections for a user who has granted access to their account. For more information, you check out its documentation.

To fetch your connections, you simply call .get_connections() method with proper GET querystring:

application.get_connections()
{u'_total': 13,
 u'values': [{u'apiStandardProfileRequest': {u'headers': {u'_total': 1,
     u'values': [{u'name': u'x-li-auth-token', u'value': u'name:16V1033'}]},
    u'url': u'https://api.linkedin.com/v1/people/lddvGtD5xk'},
   u'firstName': u'John',
   u'headline': u'Ruby',
   u'id': u'2323SDFSsfd34',
   u'industry': u'Computer Software',
   u'lastName': u'DOE',
   u'location': {u'country': {u'code': u'tr'}, u'name': u'Istanbul, Turkey'},
   u'siteStandardProfileRequest': {u'url': u'https://www.linkedin.com/profile/view?id=049430532&authType=name&authToken=16V8&trk=api*a101945*s101945*'}},
   ....

application.get_connections(selectors=['headline', 'first-name', 'last-name'], params={'start':10, 'count':5})

Search API

There are 3 types of Search APIs. One is the People Search API, second one is the Company Search API and the last one is Jobs Search API.

The People Search API returns information about people. It lets you implement most of what shows up when you do a search for "People" in the top right box on LinkedIn.com. You can get more information from here.

application.search_profile(selectors=[{'people': ['first-name', 'last-name']}], params={'keywords': 'apple microsoft'})
# Search URL is https://api.linkedin.com/v1/people-search:(people:(first-name,last-name))?keywords=apple%20microsoft

{u'people': {u'_count': 10,
  u'_start': 0,
  u'_total': 2,
  u'values': [
   {u'firstName': u'John', u'lastName': 'Doe'},
   {u'firstName': u'Jane', u'lastName': u'Doe'}
  ]}}

The Company Search API enables search across company pages. You can get more information from here.

application.search_company(selectors=[{'companies': ['name', 'universal-name', 'website-url']}], params={'keywords': 'apple microsoft'})
# Search URL is https://api.linkedin.com/v1/company-search:(companies:(name,universal-name,website-url))?keywords=apple%20microsoft

{u'companies': {u'_count': 10,
  u'_start': 0,
  u'_total': 1064,
  u'values': [{u'name': u'Netflix',
    u'universalName': u'netflix',
    u'websiteUrl': u'httsp://netflix.com'},
   {u'name': u'Alliance Data',
    u'universalName': u'alliance-data',
    u'websiteUrl': u'www.alliancedata.com'},
   {u'name': u'GHA Technologies',
    u'universalName': u'gha-technologies',
    u'websiteUrl': u'www.gha-associates.com'},
   {u'name': u'Intelligent Decisions',
    u'universalName': u'intelligent-decisions',
    u'websiteUrl': u'https://www.intelligent.net'},
   {u'name': u'Mindfire Solutions',
    u'universalName': u'mindfire-solutions',
    u'websiteUrl': u'www.mindfiresolutions.com'},
   {u'name': u'Babel Media',
    u'universalName': u'babel-media',
    u'websiteUrl': u'https://www.babelmedia.com/'},
   {u'name': u'Milestone Technologies',
    u'universalName': u'milestone-technologies',
    u'websiteUrl': u'www.milestonepowered.com'},
   {u'name': u'Denali Advanced Integration',
    u'universalName': u'denali-advanced-integration',
    u'websiteUrl': u'www.denaliai.com'},
   {u'name': u'MicroAge',
    u'universalName': u'microage',
    u'websiteUrl': u'www.microage.com'},
   {u'name': u'TRUSTe',
    u'universalName': u'truste',
    u'websiteUrl': u'https://www.truste.com/'}]}}

The Job Search API enables search across LinkedIn's job postings. You can get more information from here.

application.search_job(selectors=[{'jobs': ['id', 'customer-job-code', 'posting-date']}], params={'title': 'python', 'count': 2})
{u'jobs': {u'_count': 2,
  u'_start': 0,
  u'_total': 206747,
  u'values': [{u'customerJobCode': u'0006YT23WQ',
    u'id': 5174636,
    u'postingDate': {u'day': 21, u'month': 3, u'year': 2013}},
   {u'customerJobCode': u'00023CCVC2',
    u'id': 5174634,
    u'postingDate': {u'day': 21, u'month': 3, u'year': 2013}}]}}

Group API

The Groups API provides rich access to read and interact with LinkedIn’s groups functionality. You can get more information from here. By the help of the interface, you can fetch group details, get your group memberships as well as your posts for a specific group which you are a member of.

application.get_group(41001)
{u'id': u'41001', u'name': u'Object Oriented Programming'}

application.get_memberships(params={'count': 20})
{u'_total': 1,
 u'values': [{u'_key': u'25827',
   u'group': {u'id': u'25827', u'name': u'Python Community'},
   u'membershipState': {u'code': u'member'}}]}

application.get_posts(41001)

application.get_post_comments(
    %POST_ID%,
    selectors=[
        {"creator": ["first-name", "last-name"]},
        "creation-timestamp",
        "text"
    ],
    params={"start": 0, "count": 20}
)

You can also submit a new post into a specific group.

title = 'Scala for the Impatient'
summary = 'A new book has been published'
submitted_url = 'https://horstmann.com/scala/'
submitted_image_url = 'https://horstmann.com/scala/images/cover.png'
description = 'It is a great book for the keen beginners. Check it out!'

application.submit_group_post(41001, title, summary, submitted_url, submitted_image_url, description)

Company API

The Company API:

  • Retrieves and displays one or more company profiles based on the company ID or universal name.
  • Returns basic company profile data, such as name, website, and industry.
  • Returns handles to additional company content, such as RSS stream and Twitter feed.

You can query a company with either its ID or Universal Name. For more information, you can check out the documentation here.

application.get_companies(company_ids=[1035], universal_names=['apple'], selectors=['name'], params={'is-company-admin': 'true'})
# 1035 is Microsoft
# The URL is as follows: https://api.linkedin.com/v1/companies::(1035,universal-name=apple)?is-company-admin=true

{u'_total': 2,
 u'values': [{u'_key': u'1035', u'name': u'Microsoft'},
  {u'_key': u'universal-name=apple', u'name': u'Apple'}]}

# Get the latest updates about Microsoft
application.get_company_updates(1035, params={'count': 2})
{u'_count': 2,
 u'_start': 0,
 u'_total': 58,
 u'values': [{u'isCommentable': True,
   u'isLikable': True,
   u'isLiked': False,
   u'numLikes': 0,
   u'timestamp': 1363855486620,
   u'updateComments': {u'_total': 0},
   u'updateContent': {u'company': {u'id': 1035, u'name': u'Microsoft'},
    u'companyJobUpdate': {u'action': {u'code': u'created'},
     u'job': {u'company': {u'id': 1035, u'name': u'Microsoft'},
      u'description': u'Job Category: SalesLocation: Sacramento, CA, USJob ID: 812346-106756Division: Retail StoresStore...',
      u'id': 5173319,
      u'locationDescription': u'Sacramento, CA, US',
      u'position': {u'title': u'Store Manager, Specialty Store'},
      u'siteJobRequest': {u'url': u'https://www.linkedin.com/jobs?viewJob=&jobId=5173319'}}}},
   u'updateKey': u'UNIU-c1035-5720424522989961216-FOLLOW_CMPY',
   u'updateType': u'CMPY'},
  {u'isCommentable': True,
   u'isLikable': True,
   u'isLiked': False,
   u'numLikes': 0,
   u'timestamp': 1363855486617,
   u'updateComments': {u'_total': 0},
   u'updateContent': {u'company': {u'id': 1035, u'name': u'Microsoft'},
    u'companyJobUpdate': {u'action': {u'code': u'created'},
     u'job': {u'company': {u'id': 1035, u'name': u'Microsoft'},
      u'description': u'Job Category: Software Engineering: TestLocation: Redmond, WA, USJob ID: 794953-81760Division:...',
      u'id': 5173313,
      u'locationDescription': u'Redmond, WA, US',
      u'position': {u'title': u'Software Development Engineer in Test, Senior-IEB-MSCIS (794953)'},
      u'siteJobRequest': {u'url': u'https://www.linkedin.com/jobs?viewJob=&jobId=5173313'}}}},
   u'updateKey': u'UNIU-c1035-5720424522977378304-FOLLOW_CMPY',
   u'updateType': u'CMPY'}]}

You can follow or unfollow a specific company as well.

application.follow_company(1035)
True

application.unfollow_company(1035)
True

Job API

The Jobs APIs provide access to view jobs and job data. You can get more information from its documentation.

application.get_job(job_id=5174636)
{u'active': True,
 u'company': {u'id': 2329, u'name': u'Schneider Electric'},
 u'descriptionSnippet': u"The Industrial Accounts Sales Manager is a quota carrying senior sales position principally responsible for generating new sales and growing company's share of wallet within the industrial business, contracting business and consulting engineering business. The primary objective is to build and establish strong and lasting relationships with technical teams and at executive level within specific in",
 u'id': 5174636,
 u'position': {u'title': u'Industrial Accounts Sales Manager'},
 u'postingTimestamp': 1363860033000}

You can also fetch you job bookmarks.

application.get_job_bookmarks()
{u'_total': 0}

Share API

Network updates serve as one of the core experiences on LinkedIn, giving users the ability to share rich content to their professional network. You can get more information from here.

application.submit_share('Posting from the API using JSON', 'A title for your share', None, 'https://www.linkedin.com', 'https://d.pr/3OWS')
{'updateKey': u'UNIU-8219502-5705061301949063168-SHARE'
 'updateURL': 'https://www.linkedin.com/updates?discuss=&scope=8219502&stype=M&topic=5705061301949063168&type=U&a=aovi'}

Network API

The Get Network Updates API returns the users network updates, which is the LinkedIn term for the user's feed. This call returns most of what shows up in the middle column of the LinkedIn.com home page, either for the member or the member's connections. You can get more information from here.

There are many network update types. You can look at them by importing NETWORK_UPDATES enumeration.

from linkedin.linkedin import NETWORK_UPDATES
print NETWORK_UPDATES.enums
{'APPLICATION': 'APPS',
 'CHANGED_PROFILE': 'PRFU',
 'COMPANY': 'CMPY',
 'CONNECTION': 'CONN',
 'EXTENDED_PROFILE': 'PRFX',
 'GROUP': 'JGRP',
 'JOB': 'JOBS',
 'PICTURE': 'PICT',
 'SHARED': 'SHAR',
 'VIRAL': 'VIRL'}

update_types = (NETWORK_UPDATES.CONNECTION, NETWORK_UPDATES.PICTURE)
application.get_network_updates(update_types)

{u'_total': 1,
 u'values': [{u'isCommentable': True,
   u'isLikable': True,
   u'isLiked': False,
   u'numLikes': 0,
   u'timestamp': 1363470126509,
   u'updateComments': {u'_total': 0},
   u'updateContent': {u'person': {u'apiStandardProfileRequest': {u'headers': {u'_total': 1,
       u'values': [{u'name': u'x-li-auth-token', u'value': u'name:Egbj'}]},
      u'url': u'https://api.linkedin.com/v1/people/COjFALsKDP'},
     u'firstName': u'ozgur',
     u'headline': u'This is my headline',
     u'id': u'COjFALsKDP',
     u'lastName': u'vatansever',
     u'siteStandardProfileRequest': {u'url': u'https://www.linkedin.com/profile/view?id=46113651&authType=name&authToken=Egbj&trk=api*a101945*s101945*'}}},
   u'updateKey': u'UNIU-46113651-5718808205493026816-SHARE',
   u'updateType': u'SHAR'}]}

Invitation API

The Invitation API allows your users to invite people they find in your application to their LinkedIn network. You can get more information from here.

from linkedin.models import LinkedInRecipient, LinkedInInvitation
recipient = LinkedInRecipient(None, '[email protected]', 'John', 'Doe')
print recipient.json
{'person': {'_path': '/people/[email protected]',
  'first-name': 'John',
  'last-name': 'Doe'}}

invitation = LinkedInInvitation('Hello John', "What's up? Can I add you as a friend?", (recipient,), 'friend')
print invitation.json
{'body': "What's up? Can I add you as a friend?",
 'item-content': {'invitation-request': {'connect-type': 'friend'}},
 'recipients': {'values': [{'person': {'_path': '/people/[email protected]',
     'first-name': 'John',
     'last-name': 'Doe'}}]},
 'subject': 'Hello John'}

application.send_invitation(invitation)
True

Throttle Limits

LinkedIn API keys are throttled by default. You should take a look at the Throttle Limits Documentation to get more information about it.

python3-linkedin's People

Contributors

abraham avatar adrian-sgn avatar aurelg avatar ayyar avatar b3nelof0n avatar darune avatar dekhtiarjonathan avatar devinbarry avatar emlync avatar iacxc avatar ikudriavtsev avatar imgbotapp avatar ismix avatar ivankravets avatar jayzeng avatar johnfraney avatar kitsunde avatar lucavandro avatar lyroge avatar marshallhumble avatar marshyang avatar mblakele avatar ozgur avatar ptwobrussell avatar samuelmarks avatar yprez avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

python3-linkedin's Issues

LinkedIn API update

I just received this mail, and I guess some of you too.

The LinkedIn Developers program helps app creators and website owners provide personalized experiences to our members, gives members the ability to use their professional identity with other services, and makes it easier to share content from other sites on LinkedIn. Today, we're announcing several updates that will migrate all of our developers to the latest set of technologies used for our third-party integrations. We are also streamlining our programs, so we can provide better support to the entire LinkedIn developer community. Providing members with clarity and control over the use of their data is a fundamental priority for LinkedIn, and these changes also serve to advance this priority.

In addition to the changes listed below, all developers need to migrate to Version 2.0 of our APIs and OAuth 2.0 by March 1.

Changes to the program include:

APIs: Developers must migrate their apps to our new APIs.

  • Sign In with LinkedIn: Sign In with LinkedIn enables members to choose a more convenient way to log-in to third party apps and allows those apps to learn more about their new user. This API will only recognize a new "Lite Profile" permission, which supports a reduced set of member profile fields. See the documentation for more details.
  • Share on LinkedIn: Share on LinkedIn lets a member more easily share relevant information to their network and others on the LinkedIn platform. This API has the same functionality as before. See the documentation for the new format.
  • Manage Company Pages: These APIs are being merged into the LinkedIn Marketing Developer Program and access will be restricted to those participating developers, as part of our long-term effort to provide expanded support and a better experience for marketing partners.

Authentication, SDKs, and Plugins: We are also deprecating several obsolete or seldomly-used products and technologies.

  • Authentication: We will sunset OAuth 1.0 and require all developers to use OAuth 2.0, which we have supported since 2013. OAuth 2.0 is the industry standard and widely-used by the majority of people building on our platform.
  • SDKs: Our JavaScript and Mobile Software Development Kits (SDKs) will stop working. Developers will need to migrate to using OAuth 2.0 directly from their apps.
  • Plugins: Several website plugins, which were used for generating drop-in code that could quickly add enhanced LinkedIn functionality to websites, will no longer be available for use. Specifically, the Member Profile, Company Profile, Company Insider, Jobs You Might be Interested In (JYMBII), and Alumni Tool plugins will all be deprecated.

Redesigned LinkedIn Developers portal: Along with a front-end facelift, it now gives an improved ability to access and manage apps, read documentation, and find product information.

To reiterate: all developers need to migrate their apps to our newest APIs and OAuth 2.0 by March 1, 2019. To help navigate the migration process, please see the technical migration guide on the LinkedIn section of the Microsoft Docs website. Developers can expect follow-up communications via email about these changes and other future announcements about the LinkedIn Developers program.

Thank you, LinkedIn Developers Program Team

invalid redirect_uri

I have tried authenticating with OAuth 2.0 according to the instructions but I always get this error.
Could anyone help me?

Authentication issue / not clear in the README.md

I'm following the README.md to get authentication working.

I created an application on the LinkedIn Developer Console. I then exported two environment variables LINKEDIN_API_KEY LINKEDIN_API_SECRET, set to Client ID and Client Secret, respectively. When running http_api.py and opening my browser to http://localhost:8080, I was thrown away by LinkedIn with the following error : GET /code?error=invalid_scope&error_description=Your+application+has+not+been+authorized+for+the+scope+%22r_fullprofile%22. Inspired by a comment regarding another issue I managed to 'solve' the issue by changing the following in http_api.py:

--- a/examples/http_api.py
+++ b/examples/http_api.py
@@ -24,7 +24,7 @@ class LinkedInWrapper(object):
     API_KEY = environ.get('LINKEDIN_API_KEY')
     API_SECRET = environ.get('LINKEDIN_API_SECRET')
     RETURN_URL = 'http://localhost:{0}/code'.format(globals()['PORT'])
-    authentication = LinkedInAuthentication(API_KEY, API_SECRET, RETURN_URL, PERMISSIONS
+    authentication = LinkedInAuthentication(API_KEY, API_SECRET, RETURN_URL,permissions=
     application = LinkedInApplication(authentication)

I can then access my own account with my browser, e.g. with http://localhost:8080/get_profile. So far so good. From there, 3 questions:

1/ I hope blindly changing the permission in http_api.py have no side effects?

2/ WRT OAuth 1a: I guess CONSUMER_KEY and CONSUMER_SECRET refer to LINKEDIN_API_KEY/Client ID and LINKEDIN_API_SECRET/Client secret, respectively, am I right? Then, where am I supposed to find USER_TOKEN and USER_SECRET?

3/ WRT OAuth 2: I don't need it yet, but can't help noticing another terminology - do APPLICATON_KEY/ APPLICATON_SECRET (typo, btw) also correspond to LINKEDIN_API_KEY/Client ID and LINKEDIN_API_SECRET/Client secret?

I'll be glad to help with the documentation once I get it working.

linkedin.exceptions.LinkedInError: invalid_request: Unknown Error

Cloned git repository.
Installed as per instructions.
Edited /examples/http_api.py with client id, key etc.
Edited app settings return url to match.
Got authorisation code and list of routes.

Edited the examples/oauth2_code2accesstoken.py

Run it (with http_api.py running, so as to provide the return url should it be needed.

Get this ...

Traceback (most recent call last):
  File "/home/charlie/.local/lib/python3.6/site-packages/linkedin/utils.py", line 49, in raise_for_error
    response.raise_for_status()
  File "/home/charlie/.local/lib/python3.6/site-packages/requests/models.py", line 940, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 401 Client Error: Unauthorized for url: https://www.linkedin.com/uas/oauth2/accessToken

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "oauth2_code2accesstoken.py", line 22, in <module>
    result = authentication.get_access_token()
  File "/home/charlie/.local/lib/python3.6/site-packages/linkedin/linkedin.py", line 136, in get_access_token
    raise_for_error(response)
  File "/home/charlie/.local/lib/python3.6/site-packages/linkedin/utils.py", line 62, in raise_for_error
    raise ex(message)
linkedin.exceptions.LinkedInError: invalid_request: Unknown Error

Where to get USER_TOKEN & USER_SECRET

I am trying just to access my own LinkedIn profile data.

Steps followed:

  • Setup a new application
  • Get CLIENT_ID and CLIENT_SECRET

But, where to get the USER_TOKEN, USER_SECRET as mentioned here "You can simply use the 4 credentials that are provided to you in your LinkedIn application as part of an OAuth 1.0a flow and immediately access your data."? I've tried without it, and it doesn't work.

Authentication problems in httpy_api.py

When I run httpy_api.py I get a long list of exceptions that I think are coming from incorrect authentication. The readme.md file says to set LINKEDIN_API_KEY and LINKEDIN_API_SECRET, but the LinkedIn Developers page does not seem to use these, but rather Client ID and Client Secret. If I insert print functions in httpy_api.py after liw = LinkedInWrapper() I find that liw.API_KEY and liw.API_SECRET are both None.

Here is a sample of the error traceback:

Server started on port:8080
127.0.0.1 - - [19/Sep/2017 10:12:19] "GET / HTTP/1.1" 200 -
Traceback (most recent call last):
File "C:\Users\allen\Anaconda3\envs\prospecting\lib\socketserver.py", line 625, in process_request_thread
self.finish_request(request, client_address)
File "C:\Users\allen\Anaconda3\envs\prospecting\lib\socketserver.py", line 354, in finish_request
self.RequestHandlerClass(request, client_address, self)
File "C:\Users\allen\Anaconda3\envs\prospecting\lib\socketserver.py", line 681, in init
self.handle()
File "C:\Users\allen\Anaconda3\envs\prospecting\lib\http\server.py", line 422, in handle
self.handle_one_request()
File "C:\Users\allen\Anaconda3\envs\prospecting\lib\http\server.py", line 410, in handle_one_request
method()
File "C:/Py_data/LinkedIn/python3-linkedin/examples/http_api.py", line 65, in do_GET
open_new_tab(liw.authentication.authorization_url)
File "C:\Users\allen\Anaconda3\envs\prospecting\lib\site-packages\linkedin\linkedin.py", line 112, in authorization_url
qsl.append('%s=%s' % (quote(k), quote(v)))
File "C:\Users\allen\Anaconda3\envs\prospecting\lib\urllib\parse.py", line 712, in quote
return quote_from_bytes(string, safe)
File "C:\Users\allen\Anaconda3\envs\prospecting\lib\urllib\parse.py", line 737, in quote_from_bytes
raise TypeError("quote_from_bytes() expected bytes")
TypeError: quote_from_bytes() expected bytes

400 Client error : Bad Request

Hi Jonathan,

As of today, I'm facing a problem when publishing links with the API using the submit_share function. Here is the error message (I edited it to remove my access token, which is valid: if I alter it, I get an unauthorized error) :

400 Client Error: Bad Request for url: https://api.linkedin.com/v1/people/~/shares?oauth2_access_token=XXXXXXXXXXXXXXXXXX: Invalid arguments: {S_400_BAD_REQUEST=Bad request}

Any idea about what's going on / how to debug it? :)

Handling of linkedin 5xx errors

I'me getting attribute error on 502 response from linkedin, and the lib is failing to raise a handleable exception. Here is the traceback

HTTPError: 502 Server Error: internal error - server connection terminated for url: https://api.linkedin.com/v1/people/~:(id,email-address,headline,first-name,last-name,location,positions,picture-url,picture-urls::(original),public-profile-url)?oauth2_access_token=AQWwKxEgXMV4ydxOs9BAD7z2lrPk-9PDq97eMyfCHENdvmNwtPekhTjCz6UPhxf7Wqq7rsyb_lLlOxKfjFK6ErpjfVOx-ZoM8_YgXPTnMh1roZ0Q_LwAggCiQ99MmfIBp-_idV0CbA1Sbuh94gpMqRpqrSiA4gPE0S8b0TCtHBwfGY1FsAJaaV-F3cMU7CGj9RPdA1HOvI5agBeQsTz6sVHWT9JbiXqjdNC0cfhpu9PqJlLzuhKoQTXF_wKvz0KgFTPhwyLUc0qHBef2qh9h-KrAj4AoivmgZUq1Jl11m5igmXoTPNAOAg3QIbIc15C4zTz3kEgiwk2N1wGALM5KbRGI9kDMiQ&format=json
  File "linkedin/utils.py", line 49, in raise_for_error
    response.raise_for_status()
  File "requests/models.py", line 935, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
JSONDecodeError: Expecting value: line 1 column 1 (char 0)
  File "linkedin/utils.py", line 56, in raise_for_error
    response = response.json()
  File "requests/models.py", line 892, in json
    return complexjson.loads(self.text, **kwargs)
  File "simplejson/__init__.py", line 518, in loads
    return _default_decoder.decode(s)
  File "simplejson/decoder.py", line 370, in decode
    obj, end = self.raw_decode(s)
  File "simplejson/decoder.py", line 400, in raw_decode
    return self.scan_once(s, idx=_w(s, idx).end())
AttributeError: 'HTTPError' object has no attribute 'message'
  File "django/core/handlers/exception.py", line 41, in inner
    response = get_response(request)
  File "django/core/handlers/base.py", line 187, in _get_response
    response = self.process_exception_by_middleware(e, request)
  File "django/core/handlers/base.py", line 185, in _get_response
    response = wrapped_callback(request, *callback_args, **callback_kwargs)
  File "django/views/decorators/csrf.py", line 58, in wrapped_view
    return view_func(*args, **kwargs)
  File "rest_framework/viewsets.py", line 90, in view
    return self.dispatch(request, *args, **kwargs)
  File "rest_framework/views.py", line 489, in dispatch
    response = self.handle_exception(exc)
  File "rest_framework/views.py", line 449, in handle_exception
    self.raise_uncaught_exception(exc)
  File "rest_framework/views.py", line 486, in dispatch
    response = handler(request, *args, **kwargs)
  File "moberries/apps/candidates/views/candidate.py", line 378, in create
    response = super(CandidateSocialAccountViewSet, self).create(request, *args, **kwargs)
  File "rest_framework/mixins.py", line 20, in create
    serializer.is_valid(raise_exception=True)
  File "rest_framework/serializers.py", line 236, in is_valid
    self._validated_data = self.run_validation(self.initial_data)
  File "rest_framework/serializers.py", line 434, in run_validation
    value = self.validate(value)
  File "moberries/apps/candidates/serializers/candidate.py", line 420, in validate
    self.sso = self.get_sso(attrs)
  File "moberries/apps/candidates/serializers/candidate.py", line 414, in get_sso
    if sso.is_valid():
  File "moberries/apps/users/sso/base_sso.py", line 31, in is_valid
    profile_data = self.get_profile_data()
  File "moberries/apps/users/sso/linkedin.py", line 20, in get_profile_data
    'public-profile-url']
  File "linkedin/linkedin.py", line 210, in get_profile
    raise_for_error(response)
  File "linkedin/utils.py", line 66, in raise_for_error
    raise LinkedInError(error.message)

Examples of search: selectors?

Hello,

Any idea about if it is possible to narrow a company search, or generically a search, by some selector. I am thinking particularly in foundedYear. It is not a facet, and attempting just a 'keyword':'2015' does not seem to look into this field.

redirect uri does not match

Hello I was following this guide, ran the oauth2_authentication and got

http://localhost:8000/?code=xxxxxx&state=yyyy

I then passed this token into oauth2_code2accesstoken under the authorization code.

Howver, i got an error

requests.exceptions.HTTPError: 400 Client Error: Bad Request for url: https://www.linkedin.com/uas/oauth2/accessToken

Whats wrong

Application methods error

I'm testing the application methods according to the doc.

Works:

application.get_profile()
application.get_profile(selectors=['id', 'first-name', 'last-name', 'location', 'distance', 'num-connections', 'skills', 'educations'])
application.search_company(selectors=[{'companies': ['name', 'universal-name', 'website-url']}], params={'keywords': 'apple microsoft'})
application.follow_company(1035)
application.unfollow_company(1035)
application.submit_share('Posting from the API using JSON', 'A title for your share', None, 'https://www.linkedin.com', 'https://d.pr/3OWS')

Works but unexpected result:

application.get_companies(company_ids=[1035], universal_names=['apple'], selectors=['name'], params={'is-company-admin': 'true'})

{'_total': 0}

Doesn't work:

application.get_connections()
application.search_profile(selectors=[{'people': ['first-name', 'last-name']}], params={'keywords': 'apple microsoft'})
application.search_job(selectors=[{'jobs': ['id', 'customer-job-code', 'posting-date']}], params={'title': 'python', 'count': 2})
application.get_group(41001)

title = 'Scala for the Impatient'
summary = 'A new book has been published'
submitted_url = 'https://horstmann.com/scala/'
submitted_image_url = 'https://horstmann.com/scala/images/cover.png'
description = 'It is a great book for the keen beginners. Check it out!'
application.submit_group_post(41001, title, summary, submitted_url, submitted_image_url, description)

from linkedin.linkedin import NETWORK_UPDATES
update_types = (NETWORK_UPDATES.CONNECTION, NETWORK_UPDATES.PICTURE)
application.get_network_updates(update_types)

from linkedin.models import LinkedInRecipient, LinkedInInvitation
recipient = LinkedInRecipient(None, '[email protected]', 'John', 'Doe')
invitation = LinkedInInvitation('Hello John', "What's up? Can I add you as a friend?", (recipient,), 'friend')
application.send_invitation(invitation)

The same error:

Traceback (most recent call last):
  File "/Users/alceal/Dropbox/Projects/Python/.virtualenvs/linkedin-bot/lib/python3.6/site-packages/linkedin/utils.py", line 49, in raise_for_error
    response.raise_for_status()
  File "/Users/alceal/Dropbox/Projects/Python/.virtualenvs/linkedin-bot/lib/python3.6/site-packages/requests/models.py", line 935, in raise_for_status
    raise HTTPError(http_error_msg, response=self)
requests.exceptions.HTTPError: 403 Client Error: Forbidden for url: https://api.linkedin.com/v1/people/~/connections?oauth2_access_token=AQVNl-***************
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "<input>", line 1, in <module>
  File "/Users/alceal/Dropbox/Projects/Python/.virtualenvs/linkedin-bot/lib/python3.6/site-packages/linkedin/linkedin.py", line 250, in get_connections
    raise_for_error(response)
  File "/Users/alceal/Dropbox/Projects/Python/.virtualenvs/linkedin-bot/lib/python3.6/site-packages/linkedin/utils.py", line 62, in raise_for_error
    raise ex(message)
linkedin.exceptions.LinkedInForbiddenError: 403 Client Error: Forbidden for url: https://api.linkedin.com/v1/people/~/connections?oauth2_access_token=AQVNl-**************: Access to connections denied

Python-LinkedIn - Project Available on PyPI

Hello dear friends,

@ozgur @marshalllusher @abraham @ptwobrussell @SamuelMarks @EmlynC @ivankravets @devinbarry @joshowen @iacxc @yprez @jayzeng @Darune @adrian-sgn @johnfraney @lucavandro @mclate @scottydelta @mblakele @ismix @lyroge @marshyang @ikudriavtsev @kitsunde @ayyar @b3nelof0n

I would like to inform you that I have forked and mirrored the project python-linkedin which was originally created by @ozgur and converted to Python3 mainly by @marshalllusher.

I needed this library to work for a personal project and took the initiative to republish it to the PyPI Service : https://pypi.python.org/pypi/python3-linkedin

I hope you will appreciate this move, I have added quite some functionalities and tried to improve a little the documentation.

You all have been cited as contributors, and the contributions have been kept as yours during the mirroring process. I had to mirror and not fork due to the necessity of having "issues" enabled for the library.

Please feel free to comment if you disagree with anything I've done. I really intended to make it more easily accessible for anyone.

Have a great week,

Best Regards,

Jonathan DEKHTIAR

Invalid redirect URI on http_api and authentication

Hi,

I saw this post but the fixes don't seem to work with python 3.6?

https://gist.github.com/dergachev/7028596

I've added the following urls for redirect uris:

http://localhost:8080/code
https://localhost:8080/code/
http://localhost:8080/code/signin-linkedin
https://localhost:8080/code/signin-linkedin
https%3A//locahost%3A8080/code/
https://appname.auth0.com/login/callback
https://appname.auth0.com

This happens when trying the code on:

http_api.py and on oauth2_authentication.py

Please advise what additional information you might need.

Authentication Problem when collecting token

Hey guys,

I'm trying to connect to the basic profile api through jupyter. When I click on the link to get my token and authorize my application I get this error on the link:

http://localhost:8000/callback/?error=invalid_scope&error_description=Your+application+has+not+been+authorized+for+the+scope+%22r_fullprofile%22#!

I read that now you have to apply through email to get full profile access but for me only basic profile is enough as I don't have the time to wait for linked in to approve this. Is there a way to get around this problem? Maybe i can choose parameters for linkedin.PERMISSIONS.enums.values()?

I'm a bit new to python and have to do this application for a school project. Some help would be greatly appreciate and thanks for making the updates for python 3!!

Does LinkedIn still support the localhost callback?

Hey,

I tried to follow the instruction of HTTP API example, but it is failed due to this error:

line 129, in get_access_token
assert self.authorization_code, 'You must first get the authorization code'

It seems that it does not go to "parsedurl.path in ['/code/', '/code']" section. Does LinkedIn still support the localhost callback?

company search example returning no results

application.get_companies(company_ids=[1035], universal_names=['apple'], selectors=['name'], params={'is-company-admin': 'true'})

returns:

{'_total': 0}

also, https://developer.linkedin.com/documents/company-lookup-api-and-fields is a dead link.

Was this search revoked in the api recently? Usually I get access denied when something isn't available on the free api, but this returns no results which is strange.

localhost refused to connect

I followed the 'Production Authentication' steps, with "http://localhost:8080/code" in the Authorized Redirect URL's. After running the script, the print (authentication.authorization_url) statement gives,

https://www.linkedin.com/uas/oauth2/authorization?response_type=code&client_id=MY_CLIENT_ID&scope=r_basicprofile%20r_emailaddress%20w_share%20rw_company_admin%20r_fullprofile%20r_contactinfo&state=82d1166c8138c898891583357c480e12&redirect_uri=http%3A//localhost%3A8080

(where MY_CLIENT_ID is a 14-char string). When I go to http://localhost:8080 I see "This site can’t be reached / localhost refused to connect."

Is something missing?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.