Python Language
Webbskrapning med Python
Sök…
Introduktion
Webskrapning är en automatiserad, programmatisk process genom vilken data ständigt kan "skrapas" från webbsidor. Även känd som skärmskrapning eller skörd på webben, kan webbskrapning tillhandahålla omedelbar data från alla offentligt tillgängliga webbsidor. På vissa webbplatser kan webbskrotning vara olagligt.
Anmärkningar
Användbara Python-paket för webbskrapning (alfabetisk ordning)
Skicka förfrågningar och samla in data
requests
Ett enkelt, men kraftfullt paket för att göra HTTP-förfrågningar.
requests-cache
Cache för requests
; cachedata är mycket användbart. Under utveckling betyder det att du kan undvika att träffa en webbplats onödigt. När du kör en riktig samling betyder det att om din skrapa kraschar av någon anledning (kanske du inte hanterade något ovanligt innehåll på webbplatsen ...? Kanske sajten gick ned ...?) Kan du upprepa samlingen mycket snabbt där du slutade.
scrapy
Användbart för att bygga webbsökare, där du behöver något kraftfullare än att använda requests
och iterera igenom sidor.
selenium
Pythonbindningar för Selenium WebDriver, för webbläsarautomation. Att använda requests
att göra HTTP-förfrågningar direkt är ofta enklare för att hämta webbsidor. Detta förblir emellertid ett användbart verktyg när det inte går att replikera det önskade beteendet på en webbplats med enbart requests
, särskilt när JavaScript krävs för att återge element på en sida.
HTML-parsning
BeautifulSoup
Fråga HTML- och XML-dokument med hjälp av ett antal olika parsers (Pythons inbyggda HTML Parser, html5lib
, lxml
eller lxml.html
)
lxml
Bearbetar HTML och XML. Kan användas för att fråga och välja innehåll från HTML-dokument via CSS-väljare och XPath.
Grundläggande exempel på att använda förfrågningar och lxml för att skrapa lite data
# For Python 2 compatibility.
from __future__ import print_function
import lxml.html
import requests
def main():
r = requests.get("https://httpbin.org")
html_source = r.text
root_element = lxml.html.fromstring(html_source)
# Note root_element.xpath() gives a *list* of results.
# XPath specifies a path to the element we want.
page_title = root_element.xpath('/html/head/title/text()')[0]
print(page_title)
if __name__ == '__main__':
main()
Underhålla webbskrapningssession med förfrågningar
Det är en bra idé att hålla en webbskrapningssession för att kvarstå cookies och andra parametrar. Dessutom kan det resultera i en prestandaförbättring eftersom requests.Session
återanvänder den underliggande TCP-anslutningen till en värd:
import requests
with requests.Session() as session:
# all requests through session now have User-Agent header set
session.headers = {'User-Agent': 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'}
# set cookies
session.get('http://httpbin.org/cookies/set?key=value')
# get cookies
response = session.get('http://httpbin.org/cookies')
print(response.text)
Skrapning med Scrapy-ramverket
Först måste du ställa in ett nytt Scrapy-projekt. Ange en katalog där du vill lagra din kod och köra:
scrapy startproject projectName
För att skrapa behöver vi en spindel. Spindlar definierar hur en viss webbplats ska skrapas. Här är koden för en spindel som följer länkarna till de toppröstade frågorna om StackOverflow och skrapar lite data från varje sida ( källa ):
import scrapy
class StackOverflowSpider(scrapy.Spider):
name = 'stackoverflow' # each spider has a unique name
start_urls = ['http://stackoverflow.com/questions?sort=votes'] # the parsing starts from a specific set of urls
def parse(self, response): # for each request this generator yields, its response is sent to parse_question
for href in response.css('.question-summary h3 a::attr(href)'): # do some scraping stuff using css selectors to find question urls
full_url = response.urljoin(href.extract())
yield scrapy.Request(full_url, callback=self.parse_question)
def parse_question(self, response):
yield {
'title': response.css('h1 a::text').extract_first(),
'votes': response.css('.question .vote-count-post::text').extract_first(),
'body': response.css('.question .post-text').extract_first(),
'tags': response.css('.question .post-tag::text').extract(),
'link': response.url,
}
Spara dina spindelklasser i projectName\spiders
. I detta fall - projectName\spiders\stackoverflow_spider.py
.
Nu kan du använda din spindel. Prova till exempel att köra (i projektets katalog):
scrapy crawl stackoverflow
Ändra Scrapy användaragent
Ibland blockeras standard Scrapy-användaragenten ( "Scrapy/VERSION (+http://scrapy.org)"
av värden. För att ändra standardanvändaragentens öppna settings.py , avmarkera och redigera följande rad till vad du än vill.
#USER_AGENT = 'projectName (+http://www.yourdomain.com)'
Till exempel
USER_AGENT = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_4) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36'
Skrapa med hjälp av BeautifulSoup4
from bs4 import BeautifulSoup
import requests
# Use the requests module to obtain a page
res = requests.get('https://www.codechef.com/problems/easy')
# Create a BeautifulSoup object
page = BeautifulSoup(res.text, 'lxml') # the text field contains the source of the page
# Now use a CSS selector in order to get the table containing the list of problems
datatable_tags = page.select('table.dataTable') # The problems are in the <table> tag,
# with class "dataTable"
# We extract the first tag from the list, since that's what we desire
datatable = datatable_tags[0]
# Now since we want problem names, they are contained in <b> tags, which are
# directly nested under <a> tags
prob_tags = datatable.select('a > b')
prob_names = [tag.getText().strip() for tag in prob_tags]
print prob_names
Skrapning med Selenium WebDriver
Vissa webbplatser gillar inte att skrotas. I dessa fall kan du behöva simulera en riktig användare som arbetar med en webbläsare. Selenium lanserar och kontrollerar en webbläsare.
from selenium import webdriver
browser = webdriver.Firefox() # launch firefox browser
browser.get('http://stackoverflow.com/questions?sort=votes') # load url
title = browser.find_element_by_css_selector('h1').text # page title (first h1 element)
questions = browser.find_elements_by_css_selector('.question-summary') # question list
for question in questions: # iterate over questions
question_title = question.find_element_by_css_selector('.summary h3 a').text
question_excerpt = question.find_element_by_css_selector('.summary .excerpt').text
question_vote = question.find_element_by_css_selector('.stats .vote .votes .vote-count-post').text
print "%s\n%s\n%s votes\n-----------\n" % (question_title, question_excerpt, question_vote)
Selen kan göra mycket mer. Det kan modifiera webbläsarens cookies, fylla i formulär, simulera musklick, ta skärmdumpar av webbsidor och köra anpassad JavaScript.
Enkel nedladdning av webbinnehåll med urllib.request
Standardbiblioteksmodulen urllib.request
kan användas för att ladda ner webbinnehåll:
from urllib.request import urlopen
response = urlopen('http://stackoverflow.com/questions?sort=votes')
data = response.read()
# The received bytes should usually be decoded according the response's character set
encoding = response.info().get_content_charset()
html = data.decode(encoding)
En liknande modul finns också i Python 2 .
Skrapa med lock
import:
from subprocess import Popen, PIPE
from lxml import etree
from io import StringIO
Laddar ner:
user_agent = 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_11_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/55.0.2883.95 Safari/537.36'
url = 'http://stackoverflow.com'
get = Popen(['curl', '-s', '-A', user_agent, url], stdout=PIPE)
result = get.stdout.read().decode('utf8')
-s
: tyst nedladdning
-A
: flaggan för användaragent
analysera:
tree = etree.parse(StringIO(result), etree.HTMLParser())
divs = tree.xpath('//div')