Pertanyaan mengirimkan url respons selenium ke sampah


Saya belajar Python dan saya mencoba mengorek ini halaman untuk nilai tertentu pada menu tarik-turun. Setelah itu saya harus mengklik setiap item pada tabel yang dihasilkan untuk mengambil informasi spesifik. Saya dapat memilih item dan mengambil informasi di webdriver. Tapi saya tidak tahu cara meneruskan url respons ke perayapan.

driver = webdriver.Firefox()
driver.get('http://www.cppcc.gov.cn/CMS/icms/project1/cppcc/wylibary/wjWeiYuanList.jsp')
more_btn = WebDriverWait(driver, 20).until(
     EC.visibility_of_element_located((By.ID, '_button_select'))
            )  
more_btn.click()

## select specific value from the dropdown
driver.find_element_by_css_selector("select#tabJcwyxt_jiebie >     option[value='teyaoxgrs']").click()
driver.find_element_by_css_selector("select#tabJcwyxt_jieci > option[value='d11jie']").click()
search2 = driver.find_element_by_class_name('input_a2')
search2.click()
time.sleep(5)

## convert html to "nice format"
text_html=driver.page_source.encode('utf-8')
html_str=str(text_html)

## this is a hack that initiates a "TextResponse" object (taken from the Scrapy module)
resp_for_scrapy=TextResponse('none',200,{},html_str,[],None)

## convert html to "nice format"
text_html=driver.page_source.encode('utf-8')
html_str=str(text_html)

resp_for_scrapy=TextResponse('none',200,{},html_str,[],None)

Jadi ini tempat saya terjebak. Saya dapat melakukan kueri menggunakan kode di atas. Tapi Bagaimana saya bisa lulus resp_for_scrapy ke crawlspider? Saya taruh resp_for_scrapy di tempat barang tetapi itu tidak berhasil.

## spider 
class ProfileSpider(CrawlSpider):
name = 'pccprofile2'
allowed_domains = ['cppcc.gov.cn']
start_urls = ['http://www.cppcc.gov.cn/CMS/icms/project1/cppcc/wylibary/wjWeiYuanList.jsp']    

def parse(self, resp_for_scrapy):

    hxs = HtmlXPathSelector(resp_for_scrapy)
    for post in resp_for_scrapy.xpath('//div[@class="table"]//ul//li'):
        items = []
        item = Ppcprofile2Item()
        item ["name"] = hxs.select("//h1/text()").extract()
        item ["title"] = hxs.select("//div[@id='contentbody']//tr//td//text()").extract()
        items.append(item)

    ##click next page      
    while True:
        next = self.driver.findElement(By.linkText("下一页"))
        try:
            next.click()
        except:
            break

    return(items)

Setiap saran akan sangat dihargai !!!!

EDIT Saya menyertakan kelas middleware untuk memilih dari dropdown sebelum kelas laba-laba. Tetapi sekarang tidak ada kesalahan dan tidak ada hasil.

class JSMiddleware(object):
    def process_request(self, request, spider):
        driver = webdriver.PhantomJS()
         driver.get('http://www.cppcc.gov.cn/CMS/icms/project1/cppcc/wylibary/wjWeiYuanList.jsp')


    # select from the dropdown
        more_btn = WebDriverWait(driver, 20).until(
        EC.visibility_of_element_located((By.ID, '_button_select'))
                )
        more_btn.click()


        driver.find_element_by_css_selector("select#tabJcwyxt_jiebie > option[value='teyaoxgrs']").click()
        driver.find_element_by_css_selector("select#tabJcwyxt_jieci > option[value='d11jie']").click()
        search2 = driver.find_element_by_class_name('input_a2')
        search2.click()
        time.sleep(5)

        #get the response 
        body = driver.page_source
        return HtmlResponse(driver.current_url, body=body, encoding='utf-8', request=request)



class ProfileSpider(CrawlSpider):
    name = 'pccprofile2'
    rules = [Rule(SgmlLinkExtractor(allow=(),restrict_xpaths=("//div[@class='table']")), callback='parse_item')]  

    def parse_item(self, response):
    hxs = HtmlXPathSelector(response)
    items = []
    item = Ppcprofile2Item()
    item ["name"] = hxs.select("//h1/text()").extract()
    item ["title"] = hxs.select("//div[@id='contentbody']//tr//td//text()").extract()
    items.append(item)

    #click next page      
    while True:
        next = response.findElement(By.linkText("下一页"))
        try:
            next.click()
        except:
            break

    return(items)

4
2017-07-02 01:33


asal


Jawaban:


Menggunakan Unduh Middleware untuk menangkap halaman yang membutuhkan selenium sebelum Anda memprosesnya secara teratur dengan Scrapy:

Unduh middleware pengunduh adalah kerangka pengait ke dalam pemrosesan permintaan / tanggapan oleh Scrapy. Ini adalah sistem ringan tingkat rendah untuk mengubah permintaan dan tanggapan Scrapy secara global.

Berikut contoh yang sangat mendasar menggunakan PhantomJS:

from scrapy.http import HtmlResponse
from selenium import webdriver

class JSMiddleware(object):
    def process_request(self, request, spider):
        driver = webdriver.PhantomJS()
        driver.get(request.url)

        body = driver.page_source
        return HtmlResponse(driver.current_url, body=body, encoding='utf-8', request=request)

Setelah kamu mengembalikan itu HtmlResponse (atau a TextResponse jika itu yang benar-benar Anda inginkan,, Scrapy akan berhenti memproses pengunduh dan masuk ke spider parse metode:

Jika mengembalikan objek Respons, Scrapy tidak akan repot memanggil yang lain   metode process_request () atau proses_exception (), atau yang sesuai   fungsi unduhan; itu akan mengembalikan respons itu. Proses_response ()   metode middleware terpasang selalu dipanggil pada setiap respons.

Dalam hal ini, Anda dapat terus menggunakan laba-laba Anda parse metode seperti biasa dengan HTML, kecuali bahwa JS pada halaman telah dieksekusi.

Tip: Karena Unduh Middleware process_request Metode menerima spider sebagai argumen, Anda dapat menambahkan kondisional pada spider untuk memeriksa apakah Anda perlu memproses JS sama sekali, dan itu akan memungkinkan Anda menangani halaman JS dan non-JS dengan kelas spider yang sama persis. 


18
2017-07-02 14:02



Berikut ini adalah middleware untuk Scrapy dan Selenium

from scrapy.http import HtmlResponse
from scrapy.utils.python import to_bytes
from selenium import webdriver
from scrapy import signals


class SeleniumMiddleware(object):

    @classmethod
    def from_crawler(cls, crawler):
        middleware = cls()
        crawler.signals.connect(middleware.spider_opened, signals.spider_opened)
        crawler.signals.connect(middleware.spider_closed, signals.spider_closed)
        return middleware

    def process_request(self, request, spider):
        request.meta['driver'] = self.driver  # to access driver from response
        self.driver.get(request.url)
        body = to_bytes(self.driver.page_source)  # body must be of type bytes 
        return HtmlResponse(self.driver.current_url, body=body, encoding='utf-8', request=request)

    def spider_opened(self, spider):
        self.driver = webdriver.Firefox()

    def spider_closed(self, spider):
        self.driver.close()

Juga perlu ditambahkan settings.py

DOWNLOADER_MIDDLEWARES = {
    'youproject.middlewares.selenium.SeleniumMiddleware': 200
}

Memutuskan cuaca 200 atau sesuatu yang lain berdasarkan dokumen.

Memperbarui  mode tanpa kepala firefox dengan selip dan selenium

Jika Anda ingin menjalankan firefox dalam mode tanpa kepala kemudian instal xvfb

sudo apt-get install -y xvfb

dan PyVirtualDisplay

sudo pip install pyvirtualdisplay

dan gunakan middleware ini

from shutil import which

from pyvirtualdisplay import Display
from scrapy import signals
from scrapy.http import HtmlResponse
from scrapy.utils.project import get_project_settings
from selenium import webdriver
from selenium.webdriver.firefox.firefox_binary import FirefoxBinary

settings = get_project_settings()

HEADLESS = True


class SeleniumMiddleware(object):

    @classmethod
    def from_crawler(cls, crawler):
        middleware = cls()
        crawler.signals.connect(middleware.spider_opened, signals.spider_opened)
        crawler.signals.connect(middleware.spider_closed, signals.spider_closed)
        return middleware

    def process_request(self, request, spider):
        self.driver.get(request.url)
        request.meta['driver'] = self.driver
        body = str.encode(self.driver.page_source)
        return HtmlResponse(self.driver.current_url, body=body, encoding='utf-8', request=request)

    def spider_opened(self, spider):
        if HEADLESS:
            self.display = Display(visible=0, size=(1280, 1024))
            self.display.start()
        binary = FirefoxBinary(settings.get('FIREFOX_EXE') or which('firefox'))
        self.driver = webdriver.Firefox(firefox_binary=binary)

    def spider_closed(self, spider):
        self.driver.close()
        if HEADLESS:
            self.display.stop()

dimana settings.py mengandung

FIREFOX_EXE = '/path/to/firefox.exe'

Masalahnya adalah beberapa versi firefox tidak berfungsi dengan selenium. Untuk mengatasi masalah ini Anda dapat mengunduh versi firefox 47.0.1 (versi ini bekerja dengan sempurna) dari sini kemudian ekstrak dan masukkan ke dalam proyek selenium Anda. Setelah itu ubah path firefox menjadi

FIREFOX_EXE = '/path/to/your/scrapyproject/firefox/firefox.exe'

5
2017-08-18 06:03