2016-10-31 3 views
0

Ich möchte zugreifen und dann den Inhalt aus einer Liste von URLs extrahieren. Betrachten Sie zum Beispiel diese website, ich möchte den Inhalt jedes Beitrags extrahieren. So, basierend auf den gebuchten Antworten habe ich versucht, die folgenden:Wie man den ganzen Inhalt von einer langen Liste von URLs mit scrapy zieht/extrahiert?

# -*- coding: utf-8 -*- 
import scrapy 
from selenium import webdriver 
import urllib 

class Test(scrapy.Spider): 
    name = "test" 
    allowed_domains = ["https://sfbay.craigslist.org/search/jjj?employment_type=2"] 
    start_urls = (
     'https://sfbay.craigslist.org/search/jjj?employment_type=2', 
    ) 

    def parse(self, response): 
     driver = webdriver.Firefox() 
     driver.get(response) 
     links = driver.find_elements_by_xpath('''.//a[@class='hdrlnk']''') 
     links = [x.get_attribute('href') for x in links] 
     for x in links: 
      print(x) 

Aber ich verstehe nicht, wie in einer einzigen Bewegung der gesamten Inhalt aus einer langen Liste von Links verschrotten, ohne das Ziel Urls Angabe ... Irgendeine Idee, wie man es macht? Ich versuche auch etwas ähnlich wie diese video, und ich bin immer noch stecken ....

UPDATE Basierend in @quasarseeker Antwort, die ich versucht:

from scrapy.spiders import CrawlSpider, Rule 
from scrapy.linkextractors import LinkExtractor 
from test.items import TestItems 


class TestSpider(CrawlSpider): 

name = "test" 
allowed_domains = ["https://sfbay.craigslist.org/search/jjj?employment_type=2"] 
start_urls = (
       'https://sfbay.craigslist.org/search/jjj?employment_type=2', 
      ) 


rules = ( # Rule to parse through all pages 
     Rule(LinkExtractor(allow=(), restrict_xpaths=("//a[@class='button next']",)), 
      follow=True), 
     # Rule to parse through all listings on a page 
     Rule(LinkExtractor(allow=(), restrict_xpaths=("/p[@class='row']/a",)), 
      callback="parse_obj", follow=True),) 


    def parse_obj(self, response): 
     item = TestItem() 
     item['url'] = [] 
     for link in LinkExtractor(allow=(), deny=self.allowed_domains).extract_links(response): 
      item['url'].append(link.url) 
     print('\n\n\n\n**********************\n\n\n\n',item) 
     return item 

Allerdings bin ich nicht immer alles:

2016-11-03 08:46:24 [scrapy] INFO: Scrapy 1.2.0 started (bot: test) 
2016-11-03 08:46:24 [scrapy] INFO: Overridden settings: {'NEWSPIDER_MODULE': 'test.spiders', 'BOT_NAME': 'test', 'ROBOTSTXT_OBEY': True, 'SPIDER_MODULES': ['test.spiders']} 
2016-11-03 08:46:24 [scrapy] INFO: Enabled extensions: 
['scrapy.extensions.logstats.LogStats', 'scrapy.extensions.corestats.CoreStats'] 
2016-11-03 08:46:24 [scrapy] INFO: Enabled downloader middlewares: 
['scrapy.downloadermiddlewares.robotstxt.RobotsTxtMiddleware', 
'scrapy.downloadermiddlewares.httpauth.HttpAuthMiddleware', 
'scrapy.downloadermiddlewares.downloadtimeout.DownloadTimeoutMiddleware', 
'scrapy.downloadermiddlewares.defaultheaders.DefaultHeadersMiddleware', 
'scrapy.downloadermiddlewares.useragent.UserAgentMiddleware', 
'scrapy.downloadermiddlewares.retry.RetryMiddleware', 
'scrapy.downloadermiddlewares.redirect.MetaRefreshMiddleware', 
'scrapy.downloadermiddlewares.httpcompression.HttpCompressionMiddleware', 
'scrapy.downloadermiddlewares.redirect.RedirectMiddleware', 
'scrapy.downloadermiddlewares.cookies.CookiesMiddleware', 
'scrapy.downloadermiddlewares.chunked.ChunkedTransferMiddleware', 
'scrapy.downloadermiddlewares.stats.DownloaderStats'] 
2016-11-03 08:46:24 [scrapy] INFO: Enabled spider middlewares: 
['scrapy.spidermiddlewares.httperror.HttpErrorMiddleware', 
'scrapy.spidermiddlewares.offsite.OffsiteMiddleware', 
'scrapy.spidermiddlewares.referer.RefererMiddleware', 
'scrapy.spidermiddlewares.urllength.UrlLengthMiddleware', 
'scrapy.spidermiddlewares.depth.DepthMiddleware'] 
2016-11-03 08:46:24 [scrapy] INFO: Enabled item pipelines: 
[] 
2016-11-03 08:46:24 [scrapy] INFO: Spider opened 
2016-11-03 08:46:24 [scrapy] INFO: Crawled 0 pages (at 0 pages/min), scraped 0 items (at 0 items/min) 
2016-11-03 08:46:24 [scrapy] DEBUG: Crawled (200) <GET https://sfbay.craigslist.org/robots.txt> (referer: None) 
2016-11-03 08:46:25 [scrapy] DEBUG: Crawled (200) <GET https://sfbay.craigslist.org/search/jjj?employment_type=2> (referer: None) 
2016-11-03 08:46:25 [scrapy] DEBUG: Filtered offsite request to 'sfbay.craigslist.org': <GET https://sfbay.craigslist.org/search/jjj?employment_type=2&s=100> 
2016-11-03 08:46:25 [scrapy] INFO: Closing spider (finished) 
2016-11-03 08:46:25 [scrapy] INFO: Dumping Scrapy stats: 
{'downloader/request_bytes': 516, 
'downloader/request_count': 2, 
'downloader/request_method_count/GET': 2, 
'downloader/response_bytes': 18481, 
'downloader/response_count': 2, 
'downloader/response_status_count/200': 2, 
'finish_reason': 'finished', 
'finish_time': datetime.datetime(2016, 11, 3, 14, 46, 25, 230629), 
'log_count/DEBUG': 3, 
'log_count/INFO': 7, 
'offsite/domains': 1, 
'offsite/filtered': 1, 
'request_depth_max': 1, 
'response_received_count': 2, 
'scheduler/dequeued': 1, 
'scheduler/dequeued/memory': 1, 
'scheduler/enqueued': 1, 
'scheduler/enqueued/memory': 1, 
'start_time': datetime.datetime(2016, 11, 3, 14, 46, 24, 258110)} 
2016-11-03 08:46:25 [scrapy] INFO: Spider closed (finished) 
+0

bekommen Sie alle Tags 'a' und für jede' a' erhalten 'href' attrib. – furas

Antwort

0

Ich benutze kein Selen (aber BeautifulSoup), also kann es bessere Lösung geben.

Sie können alle a Tags mit Klasse hdrlnk erhalten und dann können Sie href von diesen Tags erhalten. Jetzt haben Sie eine Liste aller Links und Sie können auf diese Seiten gehen und Inhalt bekommen.

from selenium import webdriver 

driver = webdriver.Firefox() 
driver.get('https://sfbay.craigslist.org/search/jjj?employment_type=2') 

# get all `a` with `class=hdrlnk` 
links = driver.find_elements_by_xpath('.//a[@class="hdrlnk"]') 
#links = driver.find_elements_by_css_selector('a.hdrlnk') 
#links = driver.find_elements_by_class_name('hdrlnk') 

# get all `href` from all `a` 
links = [x.get_attribute('href') for x in links] 

# visit pages 
for x in links: 
    print(x) 

    # follow link 
    driver.get(x) 

    # ... here get page content ... 

    # ... EDIT ... 

    # ... using `elements` (with `s`) ... 
    #content = driver.find_elements_by_xpath('.//*[@id="postingbody"]') 
    #content = driver.find_elements_by_css_selector('#postingbody') 
    content = driver.find_elements_by_id('postingbody') 
    #print([x.text for x in content]) 
    #print([x.text for x in content][0]) 
    print(''.join([x.text for x in content])) 

    # ... using `element` (without `s`) ... 
    #content = driver.find_element_by_xpath('.//*[@id="postingbody"]') 
    #content = driver.find_element_by_css_selector('#postingbody') 
    content = driver.find_element_by_id('postingbody') 
    print(content.text) 
+0

Vielen Dank für die Hilfe furas !, Ich bekomme die folgende Ausnahme: 'AttributeError: 'Service' Objekt hat kein Attribut 'process''. Irgendeine Idee warum das passiert? – student

+0

wahrscheinlich ist es Problem mit 'Firefox()' Treiber - verwenden Sie Ihren Treiber: Chrome, PhantomJS, etc. – furas

+0

Was ist mit dem Inhalt der Seite? ... Könnten Sie ein Beispiel für den Zugriff auf solche Inhalte bieten? .. – student

-1

Dies kann leicht mit Scrapy durchgeführt werden. Aber Sie müssen Ihre Regeln ändern und den LinkExtractor auf den X-Pfad aller Seiten, die Sie scrappen möchten, richten. In der Web-Seite, die Sie im Beispiel zur Verfügung gestellt haben, wäre es etwa so aussehen:

rules = (Rule(LinkExtractor(allow=("//p[@class='row']/a")), \ 
        callback='parse_obj', follow=True),) 

Diese Regeln ermöglichen würde, durch jeden Eintrag zu analysieren, die in der XPath enthalten ist -

/p[@class='row']/a 

und Rufen Sie dann parse_obj() auf.

Ich habe auch bemerkt, dass die Auflistungsseite auch Seitennummerierung hat. Für den Fall, dass Sie jede einzelne Seite des Listings analysieren möchten, müssen Sie eine Regel einfügen, um zuerst die Paginierungsschaltflächen zu analysieren, dann die Links auf jeder Seite und schließlich Ihre Funktion aufzurufen. Ihr Code-Finale würde etwa so aussehen:

rules = ( #Rule to parse through all pages   
      Rule (LinkExtractor(allow=(),restrict_xpaths=("//a[@class='button next']",)),    
       follow= True), 
      #Rule to parse through all listings on a page 
      Rule (LinkExtractor(allow=(),restrict_xpaths=("//p[@class='row']/a",)), 
       callback="parse_obj" , follow= True),) 
+0

Sie müssen die CrawlSpider-Klasse verwenden, damit sie funktioniert, indem Sie Ihre Klasse als Klassentest (CrawlSpider) definieren. In Ihrem Fall war es auf der Suche nach dem Standard def parse(), die wir geändert haben. Lesen Sie mehr auf sie hier - [Scrapy Crawl Spider-Docs] (https://doc.scrapy.org/en/latest/topics/spiders.html) und [Blogeinträge auf Crawl Spiders] (http://mherman.org/blog/2012/11/08/recursively-scraping-web-pages-with-scrapy/) – quasarseeker

+1

Danke nochmal !. Obwohl ich die Informationen lese, kann ich immer noch nicht herausfinden, wie ich alle URLs mit Scrapy ** verschrotten soll. Könnten Sie ein Beispiel geben? – student

+0

Mit dem CrawlSpider definieren die Regeln, welche X-Pfade durchsucht werden. Sie steuern die Spinne für die Schritte, die sie von Ihrer Start-URL bis zur Ziel-URL ausführen soll. In Ihrer Ziel-URL können Sie die Regeln so definieren, dass die Spinne alle xpaths mit der Struktur eingibt: '"/ p [@ class =' ​​row ']/a' '. Sobald dieser "Schritt" abgeschlossen ist und Spider die neue Seite besucht, können Sie sie definieren, um eine Funktion aufzurufen, mit der Sie alle Informationen auf dieser Seite analysieren können. Der Beispielcode mit den zwei Regeln, die ich in meiner Antwort geschrieben habe, sollte für Ihre Zielseite funktionieren. – quasarseeker

Verwandte Themen