業界に特化した検索エンジンをつくろう

googleの検索エンジン
-> crawlerが巡回
-> DOMを取得して配列に保存する

自作検索エンジン
-> crawlerが特定サイトを巡回
-> テキストを取得して、mongoDBに保存?

どういうアルゴリズムでリスト表示するか?
->最新のデータ
->クリック数

検索フィールド
->bodyに検索文字を含んでいた場合?

→データセットをmongoDBから取り出して、それをソートし直すのはいささか効率的でないような気がする

– タイトル、テキスト、リンク先を表示する。

そういえば、Googleにソートってないですね。
->レコメンドをどう出すか?

とりあえず、mongodbに入れるところから、始めよう。pug, sassも使いたい。
[vagrant@localhost freelance]$ mongo
MongoDB shell version: 3.2.20
connecting to: test
Server has startup warnings:
2018-07-21T18:36:29.147+0900 I CONTROL [initandlisten]
2018-07-21T18:36:29.148+0900 I CONTROL [initandlisten] ** WARNING: soft rlimits too low. rlimits set to 1024 processes, 64000 files. Number of processes should be at least 32000 : 0.5 times number of files.
> show dbs
app 0.078GB
local 0.078GB
mydb 0.078GB

SimpleHTTPServerでサーバーは立ち上がるが

app.py

import SimpleHTTPServer
SimpleHTTPServer.test()

サーバーを起動します。
[vagrant@localhost python]$ python app.py
Serving HTTP on 0.0.0.0 port 8000 …
192.168.33.1 – – [22/Jul/2018 15:47:18] “GET /test.py HTTP/1.1” 200 –

htmlファイルは表示されます。

test.py

# -*- coding: utf-8 -*-

print 'Content-type: text/html\n'
print """
<!DOCTYPE html>
<html>
<head><meta charset="utf8"><title>CGIスクリプト</title></head>
<body>
これはサーバの実行結果として生成されたHTMLです<br>
今日はです
</body></html>
"""

何故?文字化け?

192.168.33.1 – – [22/Jul/2018 16:58:46] “GET /cgi-bin/ HTTP/1.1” 403 –
192.168.33.1 – – [22/Jul/2018 17:00:00] “GET /cgi-bin/sample.py HTTP/1.1” 200 –
: そのようなファイルやディレクトリはありません
192.168.33.1 – – [22/Jul/2018 17:00:00] CGI script exit status 0x7f00
何故だ、こりゃわからんな。

日経平均株価をスクレイピング

import urllib2
from bs4 import BeautifulSoup

html = urllib2.urlopen("hogehoge")
soup = BeautifulSoup(html, "html.parser")
tag =soup.find("td", class_="hogehoge").string
print(tag.encode("utf-8"))

[vagrant@localhost python]$ python app.py
22,697.88

米ドル、ニューヨークダウ、上海も行きたい。
find_allで書くと、tracebackが出てくる。何故だ。

tag =soup.find_all("td", class_="hogehoge").string
print(len(tag))

[vagrant@localhost python]$ python app.py
Traceback (most recent call last):
File “app.py”, line 8, in
tag =soup.find_all(“td”, class_=”header_shisuu_atai1″).string
File “/home/linuxbrew/.linuxbrew/Cellar/python@2/2.7.14_4/lib/python2.7/site-packages/bs4/element.py”, line 1807, in __getattr__
“ResultSet object has no attribute ‘%s’. You’re probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?” % key
AttributeError: ResultSet object has no attribute ‘string’. You’re probably treating a list of items like a single item. Did you call find_all() when you meant to call find()?

soup.find_all(“a”)だと行けるので、find_all()の中がまずそうだ。

findとfind_allだと、書き方が違うのか。。。リストは行けるんだが。。
[

22,697.88

,

111.38

,

25,058.12

,

2,829.27

]

‘ascii’ codec can’t encode characters と表示されたとき

import urllib2
from bs4 import BeautifulSoup

html = urllib2.urlopen("https://www.monex.co.jp/")
soup = BeautifulSoup(html, "html.parser")
tag =soup.title.string
print(tag)

エンコードできないと表示された。
[vagrant@localhost python]$ python app.py
Traceback (most recent call last):
File “app.py”, line 9, in
print(tag)
UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-6: ordinal not in range(128)

こうなったら、タグを正規表現でreplaceしようと試したが上手くいかず、イライラMaxで数時間就寝。
改めて、試したら

import urllib2
from bs4 import BeautifulSoup

html = urllib2.urlopen("https://www.monex.co.jp/")
soup = BeautifulSoup(html, "html.parser")
tag =soup.title.string
print(tag.encode("utf-8"))

なんだ、エンコードを指定するのね♪
[vagrant@localhost python]$ python app.py
マネックス証券 | ネット証券(株・アメリカ株・投資信託)

大体気分転換すると上手くいくね。

beautiful soup4をインストールしよう

pipでbeautifulsoup4を入れます。

[vagrant@localhost python]$ pip install beautifulsoup4
Collecting beautifulsoup4
Downloading https://files.pythonhosted.org/packages/a6/29/bcbd41a916ad3faf517780a0af7d0254e8d6722ff6414723eedba4334531/beautifulsoup4-4.6.0-py2-none-any.whl (86kB)
100% |################################| 92kB 186kB/s
Installing collected packages: beautifulsoup4
Successfully installed beautifulsoup4-4.6.0
You are using pip version 9.0.1, however version 10.0.1 is available.
You should consider upgrading via the ‘pip install –upgrade pip’ command.

おおおお、入ったようだ。

ん、どうやら、python3系のコードを書いてしまったよう。
python app.py
Traceback (most recent call last):
File “app.py”, line 3, in
import requests, bs4
ImportError: No module named requests

やり直します。

import urllib2
from bs4 import BeautifulSoup

html = urllib2.urlopen("https://www.monex.co.jp/")
soup = BeautifulSoup(html)

[vagrant@localhost python]$ python app.py
/home/linuxbrew/.linuxbrew/Cellar/python@2/2.7.14_4/lib/python2.7/site-packages/bs4/__init__.py:181: UserWarning: No parser was explicitly specified, so I’m using the best available HTML parser for this system (“html.parser”). This usually isn’t a problem, but if you run this code on another system, or in a different virtual environment, it may use a different parser and behave differently.

The code that caused this warning is on line 7 of the file app.py. To get rid of this warning, change code that looks like this:

BeautifulSoup(YOUR_MARKUP})

to this:

BeautifulSoup(YOUR_MARKUP, “html.parser”)

markup_type=markup_type))

html.prserが必要のようですね。

soup = BeautifulSoup(html, "html.parser")

これでOK

では、社長が大好きなマネックス(https://www.monex.co.jp/)を見てみましょう。

import urllib2
from bs4 import BeautifulSoup

html = urllib2.urlopen("https://www.monex.co.jp/")
soup = BeautifulSoup(html, "html.parser")

tag = soup.find("title")
print(tag)

おおおおおおおおおおおおおおおおおお、
ちゃんとスクレイピングできてます!

[vagrant@localhost python]$ python app.py
マネックス証券 | ネット証券(株・アメリカ株・投資信託)

import SimpleHTTPServer

SimpleHTTPServerをimportする。

[vagrant@localhost python]$ python
Python 2.7.14 (default, Mar 12 2018, 22:03:33)
[GCC 5.4.0 20160609] on linux2
Type “help”, “copyright”, “credits” or “license” for more information.
>>> import SimpleHTTPServer
>>> SimpleHTTPServer.test()
Serving HTTP on 0.0.0.0 port 8000 …
192.168.33.1 – – [21/Jul/2018 22:28:14] “GET / HTTP/1.1” 200 –
192.168.33.1 – – [21/Jul/2018 22:28:14] code 404, message File not found
192.168.33.1 – – [21/Jul/2018 22:28:14] “GET /favicon.ico HTTP/1.1” 404 –
192.168.33.1 – – [21/Jul/2018 22:28:18] “GET /app.py HTTP/1.1” 200 –

ん?どういうことだ?

pythonに慣れよう9 クラス

class Yamanote:
	pass

shinagawa = Yamanote()
shinagawa.city = "Minato-ku"
shinagawa.user = 370000
shinagawa.line = 24

shibuya = Yamanote()
shibuya.city = "Shibuya-ku"
shibuya.user = 3310000
shibuya.spot = "hachiko"

print(shinagawa.city)
print(shibuya.spot)

[vagrant@localhost python]$ python app.py
Minato-ku
hachiko

コンストラクタを使う。

class Yamanote:
	def __init__(self, city):
		self.city = city

shinagawa = Yamanote("Shinagawa-ku")
shibuya = Yamanote("Shibuya-ku")

print(shinagawa.city)
print(shibuya.city)

[vagrant@localhost python]$ python app.py
Shinagawa-ku
Shibuya-ku

クラス変数を呼び出す。

class Yamanote:
	count = 0
	def __init__(self, city):
		Yamanote.count += 1
		self.city = city

shinagawa = Yamanote("Shinagawa-ku")
shibuya = Yamanote("Shibuya-ku")
print(Yamanote.count)

ふむ。
[vagrant@localhost python]$ python app.py
2

メソッド

class Yamanote:
	count = 0
	def __init__(self, city):
		Yamanote.count += 1
		self.city = city
	def announce(self):
		print("This is " + self.city)

shinagawa = Yamanote("Shinagawa-ku")
shibuya = Yamanote("Shibuya-ku")

shinagawa.announce()
shibuya.announce()

わかるんだが、使っていかないと、慣れないね。
[vagrant@localhost python]$ python app.py
This is Shinagawa-ku
This is Shibuya-ku

@classmethod

class Yamanote:
	count = 0
	def __init__(self, city):
		Yamanote.count += 1
		self.city = city
	def announce(self):
		print("This is " + self.city)
	@classmethod
	def show_info(cls):
		print(str(cls.count) + "instances")

shinagawa = Yamanote("Shinagawa-ku")
shibuya = Yamanote("Shibuya-ku")

Yamanote.show_info()

あああああ
[vagrant@localhost python]$ python app.py
2instances

class のprivate, public

class Yamanote:
	def __init__(self, city):
		self.__city = city
	def announce(self):
		print("This is " + self.__city)

shinagawa = Yamanote("Shinagawa-ku")
shibuya = Yamanote("Shibuya-ku")

print(shinagawa.__city)

[vagrant@localhost python]$ python app.py
Traceback (most recent call last):
File “app.py”, line 12, in
print(shinagawa.__city)
AttributeError: Yamanote instance has no attribute ‘__city’
ほえ~

継承のsuperがうまくいかない。

class Yamanote:
	def __init__(self, spot):
		self.spot = spot
	def announce(self):
		print("Enjoy " + self.spot)

class Startup(Yamanote):
	def __init__(self, spot, company):
		super().__init__(spot)
		self.company = company
	def hello(self):
		print("What's up " + self.company)

harajyuku = Startup("takeshita","sm")
print(Harajyuku.spot)
Harajyuku.hello()

[vagrant@localhost python]$ python app.py
Traceback (most recent call last):
File “app.py”, line 16, in
harajyuku = Startup(“takeshita”,”sm”)
File “app.py”, line 11, in __init__
super().__init__(spot)
TypeError: super() takes at least 1 argument (0 given)
あ、python2系はエラーになるのね。。早くいってよ、もー

import math, random
print(math.pi)

pythonに慣れよう8 変数のスコープ

関数の中で変数を定義する。

def yurakucho_line():
		dep = "nagatacho"
		arrive = "yurakucho"
		print(dep + " + " +arrive)

yurakucho_line()

[vagrant@localhost python]$ python app.py
nagatacho + yurakucho

グローバルな変数

dep = "東京駅"
def yurakucho_line():
		dep = "永田町"
		arrive = "有楽町"
		print(dep + " → " +arrive)
yurakucho_line()
print(dep + "を出発しました。")

[vagrant@localhost python]$ python app.py
永田町 → 有楽町
東京駅を出発しました。

変数の中をコメントアウトする。

def yurakucho_line():
		# dep = "永田町"
		arrive = "有楽町"
		print(dep + " → " +arrive)
yurakucho_line()
print(dep + "を出発しました。")

[vagrant@localhost python]$ python app.py
東京駅 → 有楽町
東京駅を出発しました。