初めてscrapyを使ってみた


会社の人にIOTをやる会社を調べてくれと言われたので、
「IOT 会社」でググれば、いろんな情報が出てきます。
最後に、https://hnavi.co.jp (発注ナビ)に辿り着きました。
社名、資本金、住所、ホームページ、これくらいの情報でいいかなと。
Bs4はあえて使わずに、scrapyを使ってみようと思います。
(環境 python 3.8 + vscode)
1.scrapyをinstall
terminalで

pip3 install scrapy

twistedのinstallにて
windows vc++ 14 のbuilt tool がないと怒られた、でを落として、
OK
2. scrapyのプロジェクト作成
scrapy create

2. HTML解析
「iot」で検索すると、urlは

で検索結果が出る
2ページ目は,
そのURLらをターゲットにしてやっていこうと

scrapy のshell 起動

scrapy shell https://hnavi.co.jp/search/iot


2020-12-29 18:46:14 [scrapy.core.engine] DEBUG: Crawled (200)  (referer: None)
2020-12-29 18:46:15 [asyncio] DEBUG: Using proactor: IocpProactor
[s] Available Scrapy objects:
[s]   scrapy     scrapy module (contains scrapy.Request, scrapy.Selector, etc)
[s]   crawler    
[s]   item       {}
[s]   request    
[s]   response   <200 https://hnavi.co.jp/search/iot/>
[s]   settings   
[s]   spider     
[s] Useful shortcuts:
[s]   fetch(url[, redirect=True]) Fetch URL and update local objects (by default, redirects are followed)
[s]   fetch(req)                  Fetch a scrapy.Request and update local objects
[s]   shelp()           Shell help (print this help)
[s]   view(response)    View response in a browser
2020-12-29 18:46:15 [asyncio] DEBUG: Using proactor: IocpProactor

HTMLを見てみる
<div class="page-skill__content__company__head">
            <h3><a href="https://hnavi.co.jp/spa/02357/">株式会社デザインワン・ジャパン</a></h3>
            <div class="page-skill__content__company__head__review-count">
                <i class="icon icon--bubble-20x19"></i>
                <a href="https://hnavi.co.jp/spa/02357/review/">クチコミ(3件)</a>
            </div>
        </div>

会社の名前だけがあるが、詳細も欲しいね。リンクは https://hnavi.co.jp/spa/XXXX/ 
の形になってます。とにかくまずそのリンクを抽出します。
classはpage-skill__xxになるdivタグの下層にある h3タグの中にあるaタグのhref属性です。
shellで試す:


response.css('div .page-skill__content__company__head').css('h3 a::attr(href)')

結果

<Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/spa/02290/'>,
 <Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/spa/02232/'>,
 <Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/spa/02357/'>,
 <Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/spa/02190/'>,
 <Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/ecommerce/01191/'>,
 <Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/spa/02440/'>,
 <Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/spa/02447/'>,
 <Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/ecommerce/01216/'>,
 <Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/web/03759/'>,
 <Selector xpath='descendant-or-self::h3/descendant-or-self::/a/@href' data='https://hnavi.co.jp/spa/02442/'>
 

data=の値はリンクですね。
dataはget()関数で取得できそう。

iotSpider.py
import scrapy
class IotSpider(scrapy.Spider):
    name = 'hnav-iot'
    k = name.split('-')[1]

    start_urls = ['http://hnavi.co.jp/search/'+k,
    'http://hnavi.co.jp/search/'+k+'/2',
    'http://hnavi.co.jp/search/'+k+'/3',
    'http://hnavi.co.jp/search/'+k+'/4']
    def parse(self, response):
        for company in response.css('div .page-skill__content__company__head'):
            print (company.css('h3 a::attr(href)')[0].get())

ページとか考えずべた書き、一旦リンク取得した。


scrapy crawl hnav-iot --nolog


https://hnavi.co.jp/web/03779/
https://hnavi.co.jp/spa/02360/
https://hnavi.co.jp/spa/02426/
https://hnavi.co.jp/spa/02470/
https://hnavi.co.jp/spa/02445/
https://hnavi.co.jp/web/03648/
https://hnavi.co.jp/spa/02435/
https://hnavi.co.jp/web/03701/
https://hnavi.co.jp/spa/02290/
https://hnavi.co.jp/spa/02232/
https://hnavi.co.jp/spa/02357/
https://hnavi.co.jp/spa/02190/
https://hnavi.co.jp/ecommerce/01191/
https://hnavi.co.jp/spa/02440/
https://hnavi.co.jp/spa/02447/
https://hnavi.co.jp/ecommerce/01216/
https://hnavi.co.jp/web/03759/
https://hnavi.co.jp/spa/02442/
https://hnavi.co.jp/spa/02458/
https://hnavi.co.jp/spa/02351/
https://hnavi.co.jp/spa/02427/
https://hnavi.co.jp/web/03491/
https://hnavi.co.jp/spa/02341/
https://hnavi.co.jp/web/03498/
https://hnavi.co.jp/ecommerce/01204/
https://hnavi.co.jp/spa/02349/
https://hnavi.co.jp/spa/02446/
https://hnavi.co.jp/spa/02418/
https://hnavi.co.jp/spa/02448/
https://hnavi.co.jp/spa/02331/
https://hnavi.co.jp/spa/02452/
https://hnavi.co.jp/spa/02365/
https://hnavi.co.jp/spa/02413/
https://hnavi.co.jp/web/03529/
https://hnavi.co.jp/spa/02388/
https://hnavi.co.jp/spa/02309/
https://hnavi.co.jp/web/03752/
https://hnavi.co.jp/spa/02353/

上記のリンクへもう一度getして情報を取ってくる

iotDetail.py
import scrapy
class IotDetailSpider(scrapy.Spider):
    name = 'iotDetail'
    start_urls = [
       'https://hnavi.co.jp/spa/02445/'  #ここにリンクをcopy
,'https://hnavi.co.jp/spa/02351/'
,'https://hnavi.co.jp/web/03701/'
,'https://hnavi.co.jp/web/03498/'
,'https://hnavi.co.jp/spa/02341/'
,'https://hnavi.co.jp/web/03648/'
,'https://hnavi.co.jp/spa/02349/'
,'https://hnavi.co.jp/spa/02418/'
,'https://hnavi.co.jp/spa/02309/'
,'https://hnavi.co.jp/spa/02360/'
,'https://hnavi.co.jp/spa/02458/'
,'https://hnavi.co.jp/ecommerce/01204/'
,'https://hnavi.co.jp/spa/02446/'
,'https://hnavi.co.jp/spa/02435/'
,'https://hnavi.co.jp/web/03491/'
,'https://hnavi.co.jp/web/03752/'
,'https://hnavi.co.jp/spa/02353/'
,'https://hnavi.co.jp/web/03759/'
,'https://hnavi.co.jp/spa/02331/'
,'https://hnavi.co.jp/spa/02448/'
,'https://hnavi.co.jp/spa/02365/'
,'https://hnavi.co.jp/spa/02452/'
,'https://hnavi.co.jp/web/03529/'
,'https://hnavi.co.jp/spa/02413/'
,'https://hnavi.co.jp/spa/02290/'
,'https://hnavi.co.jp/spa/02232/'
,'https://hnavi.co.jp/spa/02357/'
,'https://hnavi.co.jp/spa/02190/'
,'https://hnavi.co.jp/ecommerce/01191/'
,'https://hnavi.co.jp/web/03542/'
,'https://hnavi.co.jp/spa/02447/'
,'https://hnavi.co.jp/spa/02440/'
,'https://hnavi.co.jp/spa/02388/'
,'https://hnavi.co.jp/spa/02427/'
,'https://hnavi.co.jp/spa/02426/'
,'https://hnavi.co.jp/spa/02326/'
,'https://hnavi.co.jp/spa/02442/'
]
def parse(self, response):
        cp_name = response.css('h2.company-info__title::text').get()
        r = {cp_name:{}}
        j = {}
        n=cp_name+"\t"
        # {'dddd':{'ddd':'3333','dddd':'333','dddd':'ddddd'}}
        cp_date ="N/A"
        cp_capital="N/A"
        cp_ceo = "N/A"
        cp_add ="N/A"
        cp_hp ="N/A"
        cp_person="N/A"
        cp_div ="N/A"
        for dtl in response.xpath('//h2[contains(text(), "会社情報")]/following-sibling::table').css('tr'):
            key = dtl.css('th::text').get()
            if key == '資本金':
                cp_capital=dtl.css('td::text').get()
            if key == '設立':
                cp_date=dtl.css('td::text').get()
            if key == '従業員数':
                cp_person=dtl.css('td::text').get()
            if key == '代表取締役':
                cp_ceo=dtl.css('td::text').get()
            if key == '所在地':
                cp_add=dtl.css('td::text').get()
            if key == 'ホームページ':
                cp_hp = dtl.css('td a::attr(href)').get()
            if key == '支部情報':
                cp_div = dtl.css('td::text').get()
            # yield {
            #     key:rst
            # }
        # yield {cp_name:j}
        print(cp_name+"\t"+cp_date+"\t"+cp_capital+"\t"+cp_ceo+"\t"+cp_person+"\t"+cp_add+"\t"+cp_div+"\t"+cp_hp)
        # print(cp_name,cp_date,cp_capital,cp_ceo,cp_person,cp_add,cp_div,cp_hp)

実行

scrapy crawl iotDetail --nolog 

結果

結果をcsvファイルにする場合
scrapy crawl iotDetail --nolog > iotd.csv

二つのスクリプトを一つにして、さらにべた書きをなくす、自動ページングできるように
upgrateしようと思います
メモとして残します。