9

関数を使用しているウェブサイトから検索結果をスクレイピングしようとしてい__doPostBackます。Web ページには、検索クエリごとに 10 件の結果が表示されます。さらに結果を表示するには、__doPostBackjavascript をトリガーするボタンをクリックする必要があります。いくつかの調査の後、POST リクエストはフォームのように動作し、scrapy を使用してそのフォームに入力するだけでよいことに気付きましたFormRequest。次のスレッドを使用しました。

javascript __doPostBack メソッドでスクレイピーを使用する際の問題

次のスクリプトを記述します。

# -*- coding: utf-8 -*- 
from scrapy.contrib.spiders import CrawlSpider
from scrapy.http import FormRequest
from scrapy.http import Request
from scrapy.selector import Selector
from ahram.items import AhramItem
import re

class MySpider(CrawlSpider):
    name = u"el_ahram2"

    def start_requests(self):
        search_term = u'اقتصاد'
        baseUrl = u'http://digital.ahram.org.eg/sresult.aspx?srch=' + search_term + u'&archid=1'
        requests = []
        for i in range(1, 4):#crawl first 3 pages as a test
            argument =  u"'Page$"+ str(i+1) + u"'"
            data = {'__EVENTTARGET': u"'GridView1'", '__EVENTARGUMENT': argument}
            currentPage = FormRequest(baseUrl, formdata = data, callback = self.fetch_articles)
            requests.append(currentPage)
        return requests

    def fetch_articles(self, response):
        sel = Selector(response)
        for ref in sel.xpath("//a[contains(@href,'checkpart.aspx?Serial=')]/@href").extract(): 
            yield Request('http://digital.ahram.org.eg/' + ref, callback=self.parse_items)

    def parse_items(self, response):
        sel = Selector(response)
        the_title = ' '.join(sel.xpath("//title/text()").extract()).replace('\n','').replace('\r','').replace('\t','')#* mean 'anything'
        the_authors = '---'.join(sel.xpath("//*[contains(@id,'editorsdatalst_HyperLink')]//text()").extract())
        the_text = ' '.join(sel.xpath("//span[@id='TextBox2']/text()").extract())
        the_month_year = ' '.join(sel.xpath("string(//span[@id = 'Label1'])").extract())
        the_day = ' '.join(sel.xpath("string(//span[@id = 'Label2'])").extract())
        item = AhramItem()
        item["Authors"] = the_authors
        item["Title"] = the_title
        item["MonthYear"] = the_month_year
        item["Day"] = the_day
        item['Text'] = the_text
        return item

私の問題は、「fetch_articles」が呼び出されないことです。

2014-05-27 12:19:12+0200 [scrapy] DEBUG: Web service listening on 0.0.0.0:6080
2014-05-27 12:19:13+0200 [el_ahram2] DEBUG: Crawled (200) <POST     http://digital.ahram.org.eg/sresult.aspx?srch=%D8%A7%D9%82%D8%AA%D8%B5%D8%A7%D8%AF&archid=1> (referer: None)
2014-05-27 12:19:13+0200 [el_ahram2] DEBUG: Crawled (200) <POST http://digital.ahram.org.eg/sresult.aspx?srch=%D8%A7%D9%82%D8%AA%D8%B5%D8%A7%D8%AF&archid=1> (referer: None)
2014-05-27 12:19:13+0200 [el_ahram2] DEBUG: Crawled (200) <POST http://digital.ahram.org.eg/sresult.aspx?srch=%D8%A7%D9%82%D8%AA%D8%B5%D8%A7%D8%AF&archid=1> (referer: None)
2014-05-27 12:19:13+0200 [el_ahram2] INFO: Closing spider (finished)

数日間検索した後、私は完全に立ち往生しているように感じます。私はPythonの初心者なので、おそらくエラーは些細なことです。ただし、そうでない場合、このスレッドは多くの人に役立つ可能性があります. よろしくお願いします。

4

2 に答える 2

4

あなたのコードは問題ありません。fetch_articlesが走っています。print ステートメントを追加してテストできます。

ただし、Web サイトでは、POST 要求を検証する必要があります。それらを検証するには、フォームに応答していることを証明するために、リクエスト本文にand を含める必要が__EVENTVALIDATIONあります。__VIEWSTATEこれらを取得するには、まず GET リクエストを行い、フォームからこれらのフィールドを抽出する必要があります。これを指定しないと、代わりにエラー ページが表示されます。このページには、"checkpart.aspx?Serial=" を含むリンクが含まれていないため、forループは実行されませんでした。

これが私が をどのようにセットアップstart_requestfetch_searchたかstart_requestです。

class MySpider(CrawlSpider):
    name = u"el_ahram2"

    def start_requests(self):
        search_term = u'اقتصاد'
        baseUrl = u'http://digital.ahram.org.eg/sresult.aspx?srch=' + search_term + u'&archid=1'
        SearchPage = Request(baseUrl, callback = self.fetch_search)
        return [SearchPage]

    def fetch_search(self, response):
        sel = Selector(response)
        search_term = u'اقتصاد'
        baseUrl = u'http://digital.ahram.org.eg/sresult.aspx?srch=' + search_term + u'&archid=1'
        viewstate = sel.xpath("//input[@id='__VIEWSTATE']/@value").extract().pop()
        eventvalidation = sel.xpath("//input[@id='__EVENTVALIDATION']/@value").extract().pop()
        for i in range(1, 4):#crawl first 3 pages as a test
            argument =  u"'Page$"+ str(i+1) + u"'"
            data = {'__EVENTTARGET': u"'GridView1'", '__EVENTARGUMENT': argument, '__VIEWSTATE': viewstate, '__EVENTVALIDATION': eventvalidation}
            currentPage = FormRequest(baseUrl, formdata = data, callback = self.fetch_articles)
            yield currentPage

    ...
于 2014-06-18T14:28:22.353 に答える