取得対象のHTML
このHTMLのpタグ
、およびdivタグ
のテキストをScrapyセレクターで取得する場合の取り方
<div class="info">
住所: 東京都千代田区丸の内一丁目1ー1<br/>丸の内オフィスビル1F
<p>TEL: 03-1234-5678</p>
営業時間: 10:00〜20:00
</div>
pタグのテキストを取得する
In [1]: html = """<div class="info">
...: 住所: 東京都千代田区丸の内一丁目<br/> 丸の内オフィスビル1F
...: <p>TEL: 03-1234-5678</p> 営業時間: 10:00〜20:00
...: </div>"""
In [2]: import scrapy
...: sel = scrapy.Selector(text=html)
p::text
でpタグの文字を取得できる
In [3]: sel.css("div.info p::text").get()
Out[3]: 'TEL: 03-1234-5678'
divタグのテキストを取得する
タグの中身がテキストだけなら良いが、brやpなど内部にタグがあるとdiv::text
ではすべてを取得できない
pタグの時と同じようにget()
を使うとbrタグの手前までの文字しか取得できない。
In [4]: sel.css("div::text").get()
Out[4]: '\n 住所: 東京都千代田区丸の内一丁目'
getall()
メソッドでヒットした文字列のリストを取得できるので、これをjoinすれば1つのテキストになる。
ただしdiv::text
ではdivタグ直下のテキストしかヒットしないのでpタグ(TEL)の文字列が取れない
# getallでヒットしたテキストのリストを取得
In [5]: sel.css("div::text").getall()
Out[5]: ['\n 住所: 東京都千代田区丸の内一丁目', ' 丸の内オフィスビル1F\n ', ' 営業時間: 10:00〜20:00\n']
# joinで結合
In [6]: "".join(sel.css("div::text").getall())
Out[6]: '\n 住所: 東京都千代田区丸の内一丁目 丸の内オフィスビル1F\n 営業時間: 10:00〜20:00\n'
div *::text
を使えばdivタグ以下のテキストにヒットさせることができる。
In [7]: sel.css("div *::text").getall()
Out[7]:
['\n 住所: 東京都千代田区丸の内一丁目',
' 丸の内オフィスビル1F\n ',
'TEL: 03-1234-5678',
' 営業時間: 10:00〜20:00\n']
In [8]: "".join(sel.css("div *::text").getall())
Out[8]: '\n 住所: 東京都千代田区丸の内一丁目 丸の内オフィスビル1F\n TEL: 03-1234-5678 営業時間: 10:00〜20:00\n'
::text
を使わずxpathのstring()
メソッドを使うことでも指定要素のテキストを取得できる
In [9]: sel.css("div").xpath("string()").get()
Out[9]: '\n 住所: 東京都千代田区丸の内一丁目 丸の内オフィスビル1F\n TEL: 03-1234-5678 営業時間: 10:00〜20:00\n'
(BeautifulSoupの場合の取り方)
BeautifulSoupだとtextプロパティで内部にタグがあってもテキスト取得できるので、
それと同じ感じでScrapyを使うと取りこぼすかも
In [1]: html = """<div class="info">
...: 住所: 東京都千代田区丸の内一丁目<br/> 丸の内オフィスビル1F
...: <p>TEL: 03-1234-5678</p> 営業時間: 10:00〜20:00
...: </div>"""
In [2]: from bs4 import BeautifulSoup
...: soup = BeautifulSoup(html, "html.parser")
# textプロパティでdiv要素以下の文字列を取得できる
In [3]: soup.select_one("div").text
Out[3]: '\n 住所: 東京都千代田区丸の内一丁目 丸の内オフィスビル1F\n TEL: 03-1234-5678 営業時間: 10:00〜20:00\n'
参考