Очистка Google Scholar с помощью urllib2 вместо запросов
У меня есть простой скрипт ниже, который прекрасно работает для получения списка статей из Google Scholar в поисках интересующего термина.
import urllib
import urllib2
import requests
from bs4 import BeautifulSoup
SEARCH_SCHOLAR_HOST = "https://scholar.google.com"
SEARCH_SCHOLAR_URL = "/scholar"
def searchScholar(searchStr, limit=10):
"""Search Google Scholar for articles and publications containing terms of interest"""
url = SEARCH_SCHOLAR_HOST + SEARCH_SCHOLAR_URL + "?q=" + urllib.quote_plus(searchStr) + "&ie=UTF-8&oe=UTF-8&hl=en&btnG=Search"
content = requests.get(url, verify=False).text
page = BeautifulSoup(content, 'lxml')
results = {}
count = 0
for entry in page.find_all("h3", attrs={"class": "gs_rt"}):
if count < limit:
try:
text = entry.a.text.encode("ascii", "ignore")
url = entry.a['href']
results[url] = text
count += 1
except:
pass
return results
queryStr = "Albert einstein"
pubs = searchScholar(queryStr, 10)
if len(pubs) == 0:
print "No articles found"
else:
for pub in pubs.keys():
print pub + ' ' + pubs[pub]
Однако я хочу запустить этот скрипт как приложение CGI на удаленном сервере без доступа к консоли, поэтому я не могу установить какие-либо внешние модули Python. (Мне удалось "установить" BeautifulSoup, не прибегая к pip или easy_install, просто скопировав каталог bs4 в мой каталог cgi-bin, но этот прием не работал с запросами из-за большого количества зависимостей.)
Итак, мой вопрос: возможно ли использовать встроенные модули Python urllib2 или httplib вместо запросов на получение страницы Google Scholar и затем передать ее в BeautifulSoup? Так и должно быть, потому что я нашел здесь некоторый код, который очищает Google Scholar, используя только стандартные библиотеки плюс BeautifulSoup, но он довольно запутанный. Я бы предпочел найти гораздо более простое решение, просто приспособив мой скрипт для использования стандартных библиотек вместо запросов.
Кто-нибудь может мне помочь?
2 ответа
Этого кода достаточно для выполнения простого запроса с использованием urllib2:
def get(url):
req = urllib2.Request(url)
req.add_header('User-Agent', 'Mozilla/2.0 (compatible; MSIE 5.5; Windows NT)')
return urllib2.urlopen(req).read()
если вам нужно сделать что-то более продвинутое в будущем, это будет больше кода. То, что делает запрос, упрощает использование по сравнению со стандартными библиотеками.
Передайте пользовательский агент в заголовки запроса (проверьте, какой у вас пользовательский агент ) и запрашивает параметры :
import urllib.parse
import urllib.request
headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64)'}
params_values = {
'gl': 'us',
'hl': 'en'
}
params = urllib.parse.urlencode(params_values).encode('ascii')
req = urllib.request.Request('https://scholar.google.com', params, headers)
with urllib.request.urlopen(req) as response:
html = response.read()
Однако передача пользовательского агента не предотвратит блокировку вашего запроса.
Чтобы обойти CAPTCHA или выяснить, какие прокси использовать, вы можете попробовать использовать Google Scholar API от SerpApi, который является платным API с бесплатными 100 поисковыми запросами для тестирования.
Таким образом, вам не нужно придумывать, как обойти блокировки от Google или других поисковых систем и поддерживать синтаксический анализатор с течением времени.
Код и пример в онлайн-IDE для очистки всех публикаций со всех доступных страниц:
import pandas as pd
import os, json
from serpapi import GoogleScholarSearch
from urllib.parse import urlsplit, parse_qsl
def serpapi_scrape_all_publications(query: str):
params = {
"api_key": os.getenv("API_KEY"), # your SerpApi API key
"engine": "google_scholar", # search engine
"hl": "en", # language
"q": query, # search query
"num": "100" # articles per page
}
# where data extraction happens on SerpApi backend.
search = GoogleScholarSearch(params)
publications = []
publications_is_present = True
while publications_is_present:
results = search.get_dict() # JSON -> Python dictionary
for index, publication in enumerate(results.get("organic_results", {}), start=1):
publications.append({
"title": publication.get("title"),
"link": publication.get("link"),
"result_id": publication.get("result_id"),
"snippet": publication.get("snippet"),
"inline_links": publication.get("inline_links"),
"publication_info": publication.get("publication_info")
})
# checks for the next page and updates if present
if "next" in results.get("serpapi_pagination", []):
# split URL in parts as a dict() and update "search" variable to a new page
search.params_dict.update(dict(parse_qsl(urlsplit(results["serpapi_pagination"]["next"]).query)))
else:
publications_is_present = False
print(json.dumps(publications, indent=2, ensure_ascii=False))
serpapi_scrape_all_publications(query="biology")
Выходы:
[
{
"title": "Fungal decomposition of wood: its biology and ecology",
"link": null,
"result_id": "LiWKgtH72owJ",
"snippet": "",
"inline_links": {
"serpapi_cite_link": "https://serpapi.com/search.json?engine=google_scholar_cite&q=LiWKgtH72owJ",
"cited_by": {
"total": 1446,
"link": "https://scholar.google.com/scholar?cites=10149701587489662254&as_sdt=400005&sciodt=0,14&hl=en&num=20",
"cites_id": "10149701587489662254",
"serpapi_scholar_link": "https://serpapi.com/search.json?as_sdt=400005&cites=10149701587489662254&engine=google_scholar&hl=en&num=20"
},
"related_pages_link": "https://scholar.google.com/scholar?q=related:LiWKgtH72owJ:scholar.google.com/&scioq=biology&hl=en&num=20&as_sdt=0,14",
"versions": {
"total": 6,
"link": "https://scholar.google.com/scholar?cluster=10149701587489662254&hl=en&num=20&as_sdt=0,14",
"cluster_id": "10149701587489662254",
"serpapi_scholar_link": "https://serpapi.com/search.json?as_sdt=0%2C14&cluster=10149701587489662254&engine=google_scholar&hl=en&num=20"
}
},
"publication_info": {
"summary": "ADM Rayner, L Boddy - 1988"
}
}, ... other results
]
Отказ от ответственности, я работаю в SerpApi.