Scrape ResearchGate 모든 기관 구성원을 파이썬으로
Full Code
스크랩 할 것
전제 조건
CSS 선택자를 사용한 기본 지식 스크래핑
CSS 선택기는 스타일이 적용되는 마크업 부분을 선언하므로 일치하는 태그 및 속성에서 데이터를 추출할 수 있습니다.
CSS 선택기로 스크랩하지 않은 경우 그것이 무엇인지, 장단점, 웹 스크래핑 관점에서 왜 중요한지, 그리고 가장 일반적인 접근 방식을 보여주는 전용 블로그 게시물how to use CSS selectors when web-scraping이 있습니다. 웹 스크래핑 시 CSS 선택기를 사용합니다.
별도의 가상 환경
요컨대, 동일한 시스템에서 서로 공존할 수 있는 서로 다른 Python 버전을 포함하여 설치된 라이브러리의 독립 세트를 생성하여 라이브러리 또는 Python 버전 충돌을 방지하는 것입니다.
이전에 가상 환경으로 작업한 적이 없다면 내 전용 블로그 게시물Python virtual environments tutorial using Virtualenv and Poetry을 살펴보고 익숙해지십시오.
📌참고: 이것은 이 블로그 게시물에 대한 엄격한 요구 사항이 아닙니다.
라이브러리 설치:
pip install parsel playwright
차단될 확률 감소
요청이 차단될 가능성이 있습니다. how to reduce the chance of being blocked while web-scraping을 살펴보십시오. 대부분의 웹사이트에서 차단을 우회하는 11가지 방법이 있습니다.
전체 코드
from parsel import Selector
from playwright.sync_api import sync_playwright
import re, json, time
def scrape_institution_members(institution: str):
with sync_playwright() as p:
institution_memebers = []
page_num = 1
members_is_present = True
while members_is_present:
browser = p.chromium.launch(headless=True, slow_mo=50)
page = browser.new_page()
page.goto(f"https://www.researchgate.net/institution/{institution}/members/{page_num}")
selector = Selector(text=page.content())
print(f"page number: {page_num}")
for member in selector.css(".nova-legacy-v-person-list-item"):
name = member.css(".nova-legacy-v-person-list-item__align-content a::text").get()
link = f'https://www.researchgate.net{member.css(".nova-legacy-v-person-list-item__align-content a::attr(href)").get()}'
profile_photo = member.css(".nova-legacy-l-flex__item img::attr(src)").get()
department = member.css(".nova-legacy-v-person-list-item__stack-item:nth-child(2) span::text").get()
desciplines = member.css("span .nova-legacy-e-link::text").getall()
institution_memebers.append({
"name": name,
"link": link,
"profile_photo": profile_photo,
"department": department,
"descipline": desciplines
})
# check for Page not found selector
if selector.css(".headline::text").get():
members_is_present = False
else:
time.sleep(2) # use proxies and captcha solver instead of this
page_num += 1 # increment a one. Pagination
print(json.dumps(institution_memebers, indent=2, ensure_ascii=False))
print(len(institution_memebers)) # 624 from a EM-Normandie-Business-School
browser.close()
"""
you can also render the page and extract data from the inline JSON string,
however, it's messy and from my perspective, it is easier to scrape the page directly.
"""
# https://regex101.com/r/8qjfnH/1
# extracted_data = re.findall(r"\s+RGCommons\.react\.mountWidgetTree\(({\"data\":{\"menu\".*:true})\);;",
# str(page.content()))[0]
# json_data = json.loads(extracted_data)
# print(json_data)
scrape_institution_members(institution="EM-Normandie-Business-School")
코드 설명
라이브러리 가져오기:
from parsel import Selector
from playwright.sync_api import sync_playwright
import re, json, time
암호
설명
parsel
HTML/XML 문서를 구문 분석합니다. XPath를 지원합니다.
playwright
브라우저 인스턴스로 페이지를 렌더링합니다.
re
데이터의 일부를 정규식과 일치시킵니다.json
Python 사전을 JSON 문자열로 변환합니다.time
요청 블록을 우회하는 실용적인 방법이 아닙니다. 대신 프록시/캡차 솔버를 사용하십시오.함수를 정의합니다.
def scrape_institution_members(institution: str):
# ...
암호
설명
institution: str
파이썬에게 institution
가 str
가 되어야 한다고 알려줍니다.context manager이 있는
playwright
열기:with sync_playwright() as p:
# ...
브라우저 인스턴스를 실행하고 페이지를 열고
goto
HTML/XML 파서에 대한 응답을 전달합니다.browser = p.chromium.launch(headless=True, slow_mo=50)
page = browser.new_page()
page.goto(f"https://www.researchgate.net/institution/{institution}/members/{page_num}")
selector = Selector(text=page.content())
암호
설명
p.chromium.launch()
Chromium 브라우저 인스턴스를 시작합니다.
headless
기본 값이더라도 헤드리스 모드에서 실행하도록 명시적으로 지시합니다
playwright
.slow_mo
실행 속도를 늦추라고 지시합니다
playwright
.browser.new_page()
새 페이지를 엽니다.
임시 목록을 추가하고, 페이지 번호를 설정하고, 루프 동안 루프를 종료하고 루프를 종료하기 위한 예외를 확인합니다.
institution_memebers = []
page_num = 1
members_is_present = True
while members_is_present:
# extraction code
# check for Page not found selector
if selector.css(".headline::text").get():
members_is_present = False
else:
time.sleep(2) # use proxies and captcha solver instead of this
page_num += 1 # increment a one. Pagination
각 페이지에서 구성원 결과를 반복하고 데이터를 추출하고
append
임시list
로:for member in selector.css(".nova-legacy-v-person-list-item"):
name = member.css(".nova-legacy-v-person-list-item__align-content a::text").get()
link = f'https://www.researchgate.net{member.css(".nova-legacy-v-person-list-item__align-content a::attr(href)").get()}'
profile_photo = member.css(".nova-legacy-l-flex__item img::attr(src)").get()
department = member.css(".nova-legacy-v-person-list-item__stack-item:nth-child(2) span::text").get()
desciplines = member.css("span .nova-legacy-e-link::text").getall()
institution_memebers.append({
"name": name,
"link": link,
"profile_photo": profile_photo,
"department": department,
"descipline": desciplines
})
암호
설명
css()
to parse data from the passed CSS selector(s) . 후드 아래의 모든 CSS query traslates to XPath using
csselect
package.::text
/::attr(attribute)
to extract textual or attribute data 노드에서.
get()
/getall()
to get actual data from a matched node , 또는 get a
list
of matched data from nodes .추출된 데이터, 추출된 구성원의
length
및 close
브라우저 인스턴스 인쇄:print(json.dumps(institution_memebers, indent=2, ensure_ascii=False))
print(len(institution_memebers)) # 624 from a EM-Normandie-Business-School
browser.close()
JSON 출력의 일부(첫 번째 결과는 첫 번째 멤버이고 마지막은 최신 멤버임):
[
{
"name": "Sylvaine Castellano",
"link": "https://www.researchgate.netprofile/Sylvaine-Castellano",
"profile_photo": "https://i1.rgstatic.net/ii/profile.image/341867548954625-1458518983237_Q64/Sylvaine-Castellano.jpg",
"department": "EM Normandie Business School",
"descipline": [
"Sustainable Development",
"Sustainability",
"Innovation"
]
}, ... other results
{
"name": "Constance Biron",
"link": "https://www.researchgate.netprofile/Constance-Biron-3",
"profile_photo": "https://c5.rgstatic.net/m/4671872220764/images/template/default/profile/profile_default_m.jpg",
"department": "Marketing",
"descipline": []
}
]
JSON 문자열에서 데이터 추출
doctype을 포함하여 페이지의 전체 HTML 콘텐츠를 가져올 페이지
parsel
데이터를 인쇄하고 정규식을 사용하여 데이터를 구문 분석하여 content()
를 사용하지 않고 데이터를 스크랩할 수 있습니다.페이지를 직접 구문 분석하는 것보다 이 접근 방식을 선호하는 경우를 대비하여 이 옵션도 표시하고 있습니다.
# https://regex101.com/r/8qjfnH/1
extracted_data = re.findall(r"\s+RGCommons\.react\.mountWidgetTree\(({\"data\":{\"menu\".*:true})\);;",
str(page.content()))[0]
json_data = json.loads(extracted_data)
print(json_data)
출력:
데이터를 추출하는 것이 JSON 문자열에서 실질적으로 더 설득력 있는 것처럼 보이지만
fullName
키에 액세스하는 예를 살펴보겠습니다. 👇👇👇👇👇
initState.rigel.store.account(id:\\\"AC:2176142\\\").fullName
이렇게 하면 두 가지 추가 단계가 있습니다. 사용자 ID를 찾고 비교하여 ID가 사용자 ID와 일치하는지 확인합니다.
연결
가입 |
Feature Request 💫 또는 Bug 🐞 추가
🌼
Reference
이 문제에 관하여(Scrape ResearchGate 모든 기관 구성원을 파이썬으로), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://dev.to/dmitryzub/scrape-researchgate-all-institution-members-in-python-2c5텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)