Очистка 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.

Другие вопросы по тегам