机器学习项目搭建试验 where2go

https://github.com/da248/where2go

这个项目感觉还是挺好的,虽然没给各个数据集的下载链接,也有一些莫名其妙的bug,但是错误调试提示都还挺全,能一直有进展。

(看了下这个好像不太顶用-纯html调用APIhttps://github.com/alex-engelmann/Where2Go

 

目录

1) Gathering Data

wikivoyage_xml_to_json.py

2.wikivoyage_geotags_sql.py

3.scrap_wikivoyage_banners.py

New York Times

2) EDA

Wiki voyage

更改默认保存位置

Weather

Nyt

3) Model

Webapp

Final Remarks

启动项目

Anaconda常用命令

常用算法

自然语言处理natural language processing:

推荐系统中常见的文本处理方法:

Word2vec原理

网站细节

Html

Flask后台接口

Model

模型分析

Eda

Model

基于 H-softmax 模型的梯度计算


 

here2go 是专为推荐您的地方,根据你喜欢或不喜欢的地方/字符,而不是基于有廉价航班的目的地。

有很多网站告诉你最便宜的方式去目的地和最便宜的酒店住宿。但他们忘了问你一个非常根本的问题...你知道去哪里吗?文章,如"XX的25大旅游目的地"或"YY的100个地方,你必须访问!

此应用程序的动机之一是建立一个公正的推荐系统,该系统将考虑目的地的特征,而不是查看其他人喜欢的目的地。为此,我决定使用旅行指南来收集目的地信息。我发现,Wikivoyage提供了伟大的旅游指南,告诉你关于这个地方的历史和文化,以及什么看,如何四处走动,等等。

Try it out on www.where2go.help

下一个问题是找出使用哪种模型。传统的自然语言处理推荐系统包括 TF-IDF + cos-similarity和 TF-IDF + SVD + k - means聚类等模型。这些模型可能做伟大的工作,找到类似的目的地,但我想使用模型,让我添加地方字符,如'海滩'或'酒'在我的搜索。因此,我决定去与谷歌最近创建的模型称为word2vec。Word2vec 是一个惊人的模型,它将单词转换为捕捉单词"含义"的矢量。此模型的酷功能是,您可以添加/减去单词,因为它们是矢量。例如,你可以做类似操作'king' - 'man' + 'woman' 产生 a vector that ~= 'queen'。我的 Word2vec 模型了解了 wikivoyage 文章中介绍的单词和地点的旅游特定上下文,允许矢量操作推荐类似位置。

 

使用 word2vec,我能够获得与搜索查询具有最接近语义含义的单词/目的地的建议。但是,我必须找出一种方法,确定哪些建议实际上是地理位置,哪些只是接近的话。我能够使用Wikivoyage的地理定位数据来检查这一点。

 

一旦我训练了旅行环境模型,我就构建了一个 Web 应用程序来交付我的数据科学项目。我使用 javascript 执行 AJAX 调用,将用户查询的结果更新到 MapBox map and Bootstrap to format the pages

 

*我还收集了《纽约时报》的《旅行、世界和科学》(其中有很多环保文章)新闻来丰富我的数据源,但决定将其排除在外,因为结果过于"新闻化"。

Methodology

The code folder is divided into three sections 1) data collection, 2) EDA, 3) model.

1) Gathering Data

####Wikivoyage There are three files for wikivoyage data.三个wikivoyage数据的文件

  1. wikivoyage_xml_to_json.py

The purpose of this file is to convert Wikivoyage travel guide articles to JSON format. Wikivoyage provided a data dump of its articles in XML format and I converted it to JSON format to go through exploratory data analysis with pandas.

wikivoyage_xml_to_json.py

此文件的目的是将 Wikivoyage 旅行指南文章转换为 JSON 格式。Wikivoyage 以 XML 格式提供了文章的数据转储,我将其转换为 JSON 格式,以便用pandas进行探索性数据分析。

运行:

ImportError: No module named xmltodict

图形化界面安装

ImportError: No module named pandas

图形化界面安装

Traceback (most recent call last):

  File "wikivoyage_xml_to_json.py", line 25, in

    jdata = convert_xml_to_json('data/wikivoyage/enwikivoyage-latest-pages-articles.xml')

  File "wikivoyage_xml_to_json.py", line 12, in convert_xml_to_json

    xml_str = open(filename).read()

IOError: [Errno 2] No such file or directory: 'data/wikivoyage/enwikivoyage-latest-pages-articles.xml'

在https://dumps.wikimedia.org/enwikivoyage/latest/找数据集

(py2_flask) D:\anacondaProject\where2go\code\data_collection>python wikivoyage_xml_to_json.py

成功运行该文件后在where2go\code\data_collection\data\wikivoyage获得wikivoyage.json一份,耶

2.wikivoyage_geotags_sql.py

The purpose of this file is to gather the geolocations of articles (places). Wikivoyage provided the geolocations of articles as a sql file. I created my own MySQL database to load in and query the data. I also did a bit of data cleaning in this file to remove the accents.

维基航行_地理标记_sql.py

此文件的目的是收集文章(地点)的地理位置。Wikivoyage 提供了文章的地理位置作为 sql 文件。我创建自己的 MySQL 数据库来加载和查询数据。我还在这个文件做了一些数据清理,删除口音。

(py2_flask) D:\anacondaProject\where2go\code\data_collection>python wikivoyage_geotags_sql.py

  File "wikivoyage_geotags_sql.py", line 72

    geotag_dict = create_geotag_dict():

                                      ^

SyntaxError: invalid syntax

尝试删除这个冒号

No module named pymysql.cursors

pip install pymysql

Traceback (most recent call last):

  File "wikivoyage_geotags_sql.py", line 9, in

    cursorclass=pymysql.cursors.DictCursor)

 

 pymysql.err.OperationalError: (1045, u"Access denied for user 'admin'@'localhost' (using password: NO)")

查看源码:

# Connect to the database

connection = pymysql.connect(user='admin',

                             db='wiki',

cursorclass=pymysql.cursors.DictCursor)

查看连接方法:https://www.cnblogs.com/woider/p/5926744.html

pymysql.Connect()参数说明

host(str):      MySQL服务器地址

port(int):      MySQL服务器端口号

user(str):      用户名

passwd(str):    密码

db(str):        数据库名称

charset(str):   连接编码

 

connection对象支持的方法

cursor()        使用该连接创建并返回游标

commit()        提交当前事务

rollback()      回滚当前事务

close()         关闭连接

 

cursor对象支持的方法

execute(op)     执行一个数据库的查询命令

fetchone()      取得结果集的下一行

fetchmany(size) 获取结果集的下几行

fetchall()      获取结果集中的所有行

rowcount()      返回数据条数或影响行数

close()         关闭游标对象

修改连接时用户名密码,创建数据库

pymysql.err.ProgrammingError: (1146, u"Table 'wiki.geo_tags' doesn't exist")

看项目介绍中Wikivoyage 提供了文章的地理位置作为 sql 文件,继续找数据集https://github.com/baturin/wikivoyage-listings

还是在这里找到(雾):https://dumps.wikimedia.org/hewikivoyage/latest/

pymysql.err.ProgrammingError: (1146, u"Table 'wiki.page' doesn't exist")

还在刚刚的页面找到pages.sql

下载的一个sql貌似不是英文,(האיים_הקאריביים)

看到这个貌似是官网https://www.wikidata.org/wiki/Wikidata:Wikivoyage/Resources

全语言长这样:https://www.wikivoyage.org/

英文版的地址长这样:https://en.wikivoyage.org/

同理类推:https://dumps.wikimedia.org/enwikivoyage/latest/

成功找到英文版sql

IOError: [Errno 2] No such file or directory: '../data/geotag_dict.pkl'

查看源码为输出文件,新建

成功运行

3.scrap_wikivoyage_banners.py

This file contains code that I used to scrap the banner images of articles from wikivoyage. I also used this to collect the canonical url of the wikivoyage page. I had to search destinations using a special search page on Wikivoyage to overcome minor syntax differences in place names.

此文件包含用于从 wikivoyage 中抓取文章的横幅图像的代码。我也用这个来收集wikivoyage page的标准URL。我不得不在Wikivoyage上使用一个特殊的搜索页面搜索目的地,以克服地名中的微小语法差异。

    self.locations = pkl.load(open('../../data/pickles/geotag_dict.pkl', 'rb'))

IOError: [Errno 2] No such file or directory: '../../data/pickles/geotag_dict.pkl'

复制刚刚的pkl

CONNECTION ERROR!!! RECONNECT TO  page

Traceback (most recent call last):

  File "scrap_wikivoyage_banners.py", line 109, in

    swb.scrap_banners()

  File "scrap_wikivoyage_banners.py", line 95, in scrap_banners

    img_path, wiki_url = self.get_image_and_link(key)

  File "scrap_wikivoyage_banners.py", line 57, in get_image_and_link

    return make_default_img_url(place)

NameError: global name 'make_default_img_url' is not defined

INDEX ERROR!!!  page did not exist

 

查看源码

def get_image_and_link(self, place):

       '''

       For a given place, get the canonical wikivoyage url and save the banner.

       If the banner is just a default banner, save the img path as the default

       banner to minimize duplicates.

 

       input: place as string

       output: img_path and wiki_url + (save image in the process)

       '''

 

       base_url = "https://en.wikivoyage.org/w/index.php?title=Special%3ASearch&profile=default&search="

       full_url = base_url + place.title()

 

       try:

           response = requests.get(full_url).text

           soup = BeautifulSoup(response, 'html.parser')

           wiki_url = soup.find(rel='canonical')['href']

           img_src = 'https:' + soup.select('div.topbanner a.image')[0].select('img')[0]['src']

 

       except IndexError:

           print 'INDEX ERROR!!! %s page did not exist' % place

           return make_default_img_url(place)

 

       except ConnectionError:

           print 'CONNECTION ERROR!!! RECONNECT TO %s page' % place

           return make_default_img_url(place)

 

       if 'Pagebanner_default' in img_src or 'default_banner' in img_src:

           print '%s has default banner!' % place

           img_path = 'static/banners/default.png'

 

       else:

           place = place.replace('/', '_')  # REPLACE SLASH BECAUSE IT CREATES A DIRECTORY

 

           try:

              img_response = requests.get(img_src, stream=True)

              img_path = 'static/banners/%s.png' % place

 

           except IndexError:

              print 'INDEX ERROR!!! %s page did not exist' % place

              return make_default_img_url(place)

 

           except ConnectionError:

              print 'CONNECTION ERROR!!! RECONNECT TO %s page' % place

              return make_default_img_url(place)

 

           # save the img file if it doesn't already exist. if it already exists, dont overwrite.

           if not os.path.exists('../../webapp/static/banners/%s.png' % place):

              with open('../../webapp/static/banners/%s.png' % place, 'wb') as out_file:

                  shutil.copyfileobj(img_response.raw, out_file)

              del img_response

              print '%s.png successfully created' % place

 

           else:

              print '%s.png already exists!' % place

 

       return img_path, wiki_url

def scrap_banners(self):

       '''

       Go through every key in the locations dictionary and scrape the wiki url and img_path.

       '''

       for key in self.locations.iterkeys():

           # print 'key %s,' % key

           img_path, wiki_url = self.get_image_and_link(key)

           self.locations[key]['wiki_url'] = wiki_url

           self.locations[key]['img_path'] = img_path

def load_location(self):

       '''

       load the geolocation data.

       '''

       self.locations = pkl.load(open('../../data/pickles/geotag_dict.pkl', 'rb'))

看来还是pkl中的location出问题了,查看pkl

import cPickle as pickle 

    f = open('path'

    info = pickle.load(f) 

    print info   #show file 

{'': {u'gt_lat': Decimal('56.83330000'), u'page_id': 18192, u'gt_lon': Decimal('60.58330000'), u'page_len': 27110}, '__': {u'gt_lat': Decimal('49.85944444'), u'page_id': 13920, u'gt_lon': Decimal('20.27472222'), u'page_len': 3453}, "_(')": {u'gt_lat': Decimal('-53.32000000'), u'page_id': 14305, u'gt_lon': Decimal('-70.91000000'), u'page_len': 3408}, "__'/": {u'gt_lat': Decimal('-22.92000000'), u'page_id': 13410, u'gt_lon': Decimal('-43.22000000'), u'page_len': 56927}, "/-'_": {u'gt_lat': Decimal('41.94610000'), u'page_id': 14123, u'gt_lon': Decimal('-87.66940000'), u'page_len': 28496},……

这些key真的诡异极了

尝试打印full url

CONNECTION ERROR!!! RECONNECT TO https://en.wikivoyage.org/w/index.php?title=Special%3ASearch&profile=default&search= page

尝试打印key

保存副本

更改sql语言版本后成功获得正确key

INDEX ERROR!!! https://en.wikivoyage.org/w/index.php?title=Special%3ASearch&profile=default&search=Eastern_Cuba -- did not exist

Traceback (most recent call last):

  File "scrap_wikivoyage_banners.py", line 115, in

    swb.scrap_banners()

  File "scrap_wikivoyage_banners.py", line 101, in scrap_banners

    img_path, wiki_url = self.get_image_and_link(key)

  File "scrap_wikivoyage_banners.py", line 57, in get_image_and_link

    return make_default_img_url(place)

NameError: global name 'make_default_img_url' is not defined

尝试访问url:

https://en.wikivoyage.org/w/index.php?title=Special%3ASearch&profile=default&search=Eastern_Cuba

发get请求的状态码是302

wiki可以正常访问,但不是这个网址,跳转到

https://en.wikivoyage.org/wiki/Eastern_Cuba

和make_default_img_url中的地址一样呢

https://en.wikivoyage.org/wiki/

但是https://en.wikivoyage.org/w/index.php?title=Special%3ASearch&profile=default

这个搜索页面还在

用搜索框搜索查看发出的请求是

https://en.wikivoyage.org/w/index.php?=Eastern_Cuba&sort=relevance&search=Eastern_Cuba&title=Special%3ASearch&profile=advanced&fulltext=1&advancedSearch-current=%7B%7D&ns0=1

加&fulltext=1或无该名称则不会跳转

https://en.wikivoyage.org/w/index.php?search=Eastern_Cuba&title=Special%3ASearch&profile=advanced&fulltext=1

所以URL可能没有问题

 

make_default_img_url并不是全局变量,是不是什么错误让人把它当成全局变量了

尝试修改make_default_img_url

def make_default_img_url(self, place):

       '''

       input = place

       output = return the default values for img_path and wiki_url

       '''

 

       img_path = 'static/banners/default.png'

       wiki_url = 'https://en.wikivoyage.org/wiki/%s' % place

       return img_path, wiki_url

except IndexError:

           # print 'INDEX ERROR!!! %s page did not exist' % place

           print 'INDEX ERROR!!! %s -- did not exist' % full_url

           # return make_default_img_url(place)

           return self.make_default_img_url(place)

更改后虽然还是无法访问,但可以连续运行了,最后报错如下

  File "D:\ProgramData\Anaconda3\envs\py2_flask\lib\site-packages\requests\models.py", line 753, in generate

    raise ChunkedEncodingError(e)

requests.exceptions.ChunkedEncodingError: ("Connection broken: error(10053, '')", error(10053, ''))

 

 

在特殊搜索界面看到一个Developers:

https://www.mediawiki.org/wiki/How_to_contribute

网页API:https://www.mediawiki.org/wiki/API:Web_APIs_hub

API:Geosearch:https://www.mediawiki.org/wiki/API:Geosearch

GET 请求用地理位置的附近坐标或页面名称搜索 wiki 页面。

This module is supported through the Extension:GeoData currently not installed on MediaWiki but Wikipedia. So, in this document, we will use the URL en.wikipedia.org in all API endpoints.

此模块通过扩展支持:地理数据当前未安装在 MediaWiki 上,而是维基百科。因此,在本文中,我们将在所有 API 终结点中使用 URL en.wikipedia.org。

 

GET Request[edit]

 

Search for pages near Wikimedia Foundation headquarters by specifying the geographic coordinates of its location:

api.php?action=query&list=geosearch&gscoord=37.7891838|-122.4033522&gsradius=10000&gslimit=10 [try in ApiSandbox]

通过指定维基媒体基金会总部附近的页面,指定其位置的地理坐标

API documentation:https://en.wikipedia.org/w/api.php?action=help&modules=query+geosearch

https://en.wikivoyage.org/w/api.php?action=help&modules=query

API查阅方法https://www.mediawiki.org/wiki/API:Main_page

Examples:

Fetch site info and revisions of Main Page.

api.php?action=query&prop=revisions&meta=siteinfo&titles=Main%20Page&rvprop=user|comment&continue= [open in sandbox]

 

我之前用过request.urlopen,源码为requests.get,查看这两种区别https://blog.csdn.net/dead_cicle/article/details/86747593

构造一个Request对象,然后使用urlopen拿回来的还是对象

requests是python实现的简单易用的HTTP库,返回一个HTTPresp,该类有属性:text,content,code等。

直接打印的状态码为200,但还是报错,说明请求这一步是没有问题的

(py2_flask) D:\anacondaProject\where2go\code\data_collection>python scrap_wikivoyage_banners.py

INDEX ERROR!!! https://en.wikivoyage.org/w/index.php?title=Special%3ASearch&profile=default&search=Eastern_Cuba -- did n

ot exist

查看bs:

https://blog.csdn.net/weixin_42231070/article/details/82225529

importurllib.request frombs4 importBeautifulSoup douban_path = "https://movie.douban.com"response = urllib.request.urlopen(douban_path) soup = BeautifulSoup(response, 'html.parser') # 可以接受response对象soup = BeautifulSoup(response.read().decode('utf-8'), 'html.parser') # 可以接受字符串soup = BeautifulSoup(open(test.html),'html.parser') # 可以接受本地文件

刚才尝试打印text报错编码不对,但打印soup能打印出一堆html源码

查看wiki_url成功

soup.find(rel='canonical')['href']

(py2_flask) D:\anacondaProject\where2go\code\data_collection>python scrap_wikivoyage_banners.py

https://en.wikivoyage.org/wiki/Eastern_Cuba

所以可能是取img_src的问题

'https:'+soup.select('div.topbanner a.image')[0].select('img')[0]['src']

soup.select :https://blog.csdn.net/geerniya/article/details/77842421

通过采用soup.select()方法,可以得到所需的内容。
其中关键点在于,对于所需内容的精准定位,通过()内的语句来实现

https://blog.csdn.net/weixin_40425640/article/details/79470617

select 的功能跟find和find_all 一样用来选取特定的标签,它的选取规则依赖于css,我们把它叫做css选择器,如果之前有接触过jquery ,可以发现select的选取规则和jquery有点像。

标签名不加任何修饰,会返回一个数组(所以div是标签名

类名前加点,id名前加 #

 

组合查找可以分为两种,一种是在一个tag中进行两个条件的查找,一种是树状的查找一层一层之间的查找。

print soup.select('a#link2')

选择标签名为aidlink2的tag。

猜测可能是最后的'src'下标无效

查找select('img') https://www.jianshu.com/p/ed2f044bd1fa

Tag或BeautifulSoup对象的.select()方法。

res = soup.select('#wrapperto')

-> tag's id

res = soup.select('img[src]')

-> 'img' tags有'src' attributes

res = soup.select('img[src=...]')

-> 'src' attributes是...

soup.select 查找Img src

https://www.cnblogs.com/calmzone/p/11139980.html

# soup.a.arrts  # 获取a标签所有属性和值,返回一个字典

# soup.a.attrs['href']  # 获取href属性

# soup.a['href']  # 也可简写成这种

#上面两种方式都可以获取a标签的href属性值

https://blog.csdn.net/weixin_42231070/article/details/82225529

当属性不存在时,使用 get 返回None,字典形式取值会报错

print soup.select('div.topbanner a.image')

(py2_flask) D:\anacondaProject\where2go\code\data_collection>python scrap_wikivoyage_banners.py

[]

难道这返回了一个空数组,topbanner类的div中根本就没有image类的a

查看https://en.wikivoyage.org/wiki/Eastern_Cuba的源码

发现含有topbanner类的div是有的,但是有两个,而且这个类名字只是包含,是好几个类其中有个wpb-topbanner

一个div元素为了能被多个样式表匹配到(样式复用),通常div的class中由好几段组成,如

你可能感兴趣的:(人工智能,where2go)