鸟网作者:别来这套
出自蜂鸟网-旅行摄影,原贴链接:https://m.fengniao.com/thread/10974178.html
谢谢上面回帖的朋友!其实这次登高只是我计划中的预演。本打算经过这次试探行的登山后,带上三脚架、多个镜头和照明灯、冰爪(100多块买的)等闭门瞎想准备的登山物品来一次正式的登高。平时没事总喜欢扒拉谷歌地球,对这个亚隆冰川特别好奇。百度介绍这个冰川是12公里,但我在地图上测量直线长度超过30公里!在谷歌地球上看,然乌湖和米堆冰川(他们3个挨在一起)简直无法和亚隆冰川相比。我多次在谷歌地球上一个海拔5100处山腰上,模拟拍下亚隆冰川、东嘎冰川、来古村和白日嘎三座山峰。然而连日阴雨让我的计划基本泡汤。看手机上天气预报未来无数天依然连雨,只好在第4天悻悻的结束来古村之旅,搭乘一对杭州夫妇的自驾车出村。
虽然白日嘎峰没有露面,但隐藏山里的高山湖在海拔4700米还是出现了。
漂亮的杭州自驾游女士在给小朋友发礼品。来古村客栈和小学一个院子。小学也就20多个孩子。
如果不是翻看照片,我都不知道这露出的高山湖。
由于这次登高高度不足,也可能是登高位子选的不对,对亚隆冰川的拍摄效果远远没有达到我的期待。在家好好锻炼身体吧!争取下一次的来古村之行,登到5200米海拔,用体力弥补技术的不足吧。
再见了,来古村!其实雨中的来古村也非常美,只是我一门心思想着登高,没有静下心体会而已。
还有高海拔处的野花,秋季绽放的蓝色小花,我也只是匆匆拍一下而已。
其实,和亚隆冰川对着的,高悬在村东的东嘎冰川,也非常壮观。
再见了!来古村。等我攒够了假期和钱,我会多住几天的。
应该是一个为了村里低年龄段的孩子而设立的小学。
欢迎关注 蜂鸟网微信公众号:fengniaoweixin
不久,我在 LearnML 子论坛上看到一篇帖子。楼主在这篇帖子中提到,他需要为自己的机器学习项目抓取网页数据。很多人在回帖中给出了自己的方法,主要是学习如何使用 BeautifulSoup 和 Selenium。
我曾在一些 数据科学项目中使用过 BeautifulSoup 和 Selenium。在本文中,我将告诉你如何用一些有用的数据抓取一个网页,并将其转换成 pandas 数据结构(DataFrame)。
为什么要将其转换成数据结构呢?这是因为大部分机器学习库都能处理 pandas 数据结构,并且只需少量修改就可对你的模型进行编辑。
首先,我们要在维基百科上找到一个表来转换成数据结构。我抓取的这张表,展示的是维基百科上浏览量最大的运动员数据。
其中一项大量的工作就是,通过浏览 HTML 树来得到我们需要的表。
通过 request 和 regex 库,我们开始使用 BeautifulSoup。
from bs4 import BeautifulSoup
import requests
import re
import pandas as pd
复制代码
下面,我们将从网页中提取 HTML 代码:
website_url=requests.get('https://en.wikipedia.org/wiki/Wikipedia:Multiyear_ranking_of_most_viewed_pages').text
soup=BeautifulSoup(website_url, 'lxml')
print(soup.prettify())
</a>
</li>
<li id="footer-places-disclaimer">
<a href="/wiki/Wikipedia:General_disclaimer" title="Wikipedia:General disclaimer">
Disclaimers
</a>
</li>
<li id="footer-places-contact">
<a href="//en.wikipedia.org/wiki/Wikipedia:Contact_us">
Contact Wikipedia
</a>
</li>
<li id="footer-places-mobileview">
<a class="noprint stopMobileRedirectTog
复制代码
从语料库中收集所有的表,我们有一个较小的表面区域来搜索。
wiki_tables=soup.find_all('table', class_='wikitable')
wiki_tables
复制代码
因为存在很多表,所以需要一种过滤它们的方法。
据我们所知,Cristiano Ronaldo(也就是葡萄牙足球运动员 C 罗)有一个锚标记,这可能在几个表中是独一无二的。
通过 Cristiano Ronaldo 文本,我们可以过滤那些被锚标记的表。此外,我们还发现一些包含这个锚标记的父元素。
links=[]
for table in wiki_tables:
_table=table.find('a', string=re.compile('Cristiano Ronaldo'))
if not _table:
continue
print(_table)
_parent=_table.parent
print(_parent)
links.append(_parent)
<a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
<td style="text-align: left;"><a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
</td>
<a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
<td style="text-align: left;"><a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
</td>
<a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
<td style="text-align: left;"><a href="/wiki/Cristiano_Ronaldo" title="Cristiano Ronaldo">Cristiano Ronaldo</a>
</td>
复制代码
父元素只显示单元格。
这是一个带有浏览器 web 开发工具的单元格。
parent_lst=[]
for anchor in links:
_=anchor.find_parents('tbody')
print(_)
parent_lst.append(_)
复制代码
利用 tbody,我们可以返回包含以前的锚标记的其他表。
为进一步过滤,我们可以在以下表中的不同标题进行搜索:
for i in parent_lst:
print(i[0].find('tr'))
tr>
<th>Rank*</th>
<th>Page</th>
<th>Views in millions
</th></tr>
<tr>
<th>Rank</th>
<th>Page</th>
<th>Views in millions
</th></tr>
<tr>
<th>Rank</th>
<th>Page</th>
<th>Sport</th>
<th>Views in millions
</th></tr>
复制代码
第三张看起来很像我们所需要的表。
接下来,我们开始创建必要的逻辑来提取并清理我们需要的细节。
sports_table=parent_lst[2]
complete_row=[]
for i in sports_table:
rows=i.find_all('tr')
print('\n--------row--------\n')
print(rows)
for row in rows:
cells=row.find_all('td')
print('\n-------cells--------\n')
print(cells)
if not cells:
continue
rank=cells[0].text.strip('\n')
page_name=cells[1].find('a').text
sport=cells[2].find('a').text
views=cells[3].text.strip('\n')
print('\n-------CLEAN--------\n')
print(rank)
print(page_name)
print(sport)
print(views)
complete_row.append([rank, page_name, sport, views])
for i in complete_row:
print(i)
复制代码
分解一下:
sports_table=parent_lst[2]
complete_row=[]
复制代码
下面我们从上面的列表中选择第三个元素。这就是我们需要的表。
接下来创建一个空列表,用于存储每行的详细信息。在遍历这个表的时候,建立一个循环,遍历表中的每一行,并将其保存到 rows 变量中。
for i in sports_table:
rows=i.find_all('tr')
print('\n--------row--------\n')
print(rows)
复制代码
for row in rows:
cells=row.find_all('td')
print('\n-------cells--------\n')
print(cells)
复制代码
建立了嵌套的循环。遍历上一个循环中保存的每个行。在遍历这些单元格时,我们将每个单元格保存在一个新的变量。
if not cells:
continue
复制代码
这段简短的代码允许我们在从单元格中提取文本时,避免空单元格并防止发生错误。
rank=cells[0].text.strip('\n')
page_name=cells[1].find('a').text
sport=cells[2].find('a').text
views=cells[3].text.strip('\n')
复制代码
在此,我们将各种单元格清理为纯文本格式。清除后的值保存在其列名下的变量中。
print('\n-------CLEAN--------\n')
print(rank)
print(page_name)
print(sport)
print(views)
complete_row.append([rank, page_name, sport, views])
复制代码
此处,我们向行列表添加这些值。然后输出清理后的值。
-------cells--------
[<td>13
</td>, <td style="text-align: left;"><a href="/wiki/Conor_McGregor" title="Conor McGregor">Conor McGregor</a>
</td>, <td><a href="/wiki/Mixed_martial_arts" title="Mixed martial arts">Mixed martial arts</a>
</td>, <td>43
</td>]
-------CLEAN--------
13
Conor McGregor
Mixed martial arts
43
复制代码
下面将其转换为数据结构:
headers=['Rank', 'Name', 'Sport', 'Views Mil']
df=pd.DataFrame(complete_row, columns=headers)
df
复制代码
现在你可以在机器学习项目中使用的 pandas 数据结构了。你可以使用自己喜欢的库来拟合模型数据。
作者介绍:
Tobi Olabode,对技术感兴趣,目前主要关注机器学习。
原文链接:
https://blog.devgenius.io/how-to-scrape-a-website-for-your-ml-project-c3a4d6f160c7
目前对于Python来说,使用最多的功能肯定是Python爬虫。比如抢购茅台以及刷评论,盖楼等抽奖活动贴,都可以应用到爬虫的相关知识。
而学习Python爬虫,不仅可以增加自己的知识储备,丰富自己的知识库,而且还能帮助自己增加额外的收入。
所以,今天博主将通过某个盖楼活动贴,来实现自动评论盖楼抽奖功能。本篇内容接着上一篇博文的内容进行全自动盖楼刷评论讲解。
一般来说,我们参加某个网站的盖楼抽奖活动,并不是仅仅只参加一个,而是多个盖楼活动一起参加。
这个时候,我们就需要分析评论的链接是怎么区分不同帖子进行评论的,如上篇的刷帖链接,具体格式如下:
https://club.hihonor.com/cn/forum.php?mod=post&action=reply&fid=154&tid=21089001&extra=page%3D1&replysubmit=yes&infloat=yes&handlekey=fastpost&inajax=1
这里面用于区分不同帖子的键是tid,不妨大家可以会看上一篇博文评论帖子的链接,是不是同样有一个21089001的数字。
而经过博主的测试,该网站评论post请求网址除了tid之外,其他数据是一模一样的并不需要变更。所以,我们切换新帖子评论时,只需要替换tid的值就行。
读者可以自行随便打开一个该网站的帖子,我们一般会得到如下形式的字符串帖子链接:
https://club.hihonor.com/cn/thread-26194745-1-1.html
这里,我们需要应用字符串切割知识,来获取链接字符串中的长数字字符串26194745。具体代码如下:
import re
# 获取需要评论的所有网页链接
url_start="https://club.hihonor.com/cn/forum.php?mod=post&action=reply&fid=4515&tid="
url_end="&extra=page%3D1&replysubmit=yes&infloat=yes&handlekey=fastpost&inajax=1"
url=[] # 评论网页
txt_url=[] # 提供的网页(格式不同)
f=open("随机帖子.txt", "r", encoding='utf-8')
line=f.readline() # 读取第一行
while line:
if re.match(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', line):
txt_url.append(line.strip()) # 列表增加
line=f.readline() # 读取下一行
datas=[]
headers=[]
for i in txt_url:
url_start="https://club.hihonor.com/cn/forum.php?mod=post&action=reply&fid=4515&tid="
url_end="&extra=page%3D1&replysubmit=yes&infloat=yes&handlekey=fastpost&inajax=1"
url.append(url_start + i.split("-")[1] + url_end)
这里,博主将一大堆需要评论的链接全部放到文本文件之中,然后通过读取文件获取每一行链接数据(其中用正则表达式判断链接是否合法)。
在通过遍历链接切分获取帖子标识数字字符串,最后进行拼接获取到真正的post评论链接。
在众多的网站盖楼活动中,官方网站一般都会检测是否有内容重复,一般同一个账号多次评论重复的内容,肯定会被禁止评论一段时间。
所以,我们需要将评论的内容多样化,比如说这个网站要我们称赞手机性能进行盖楼抽奖,那么我们就需要备用一些评论文字,方便程序随机获取。
具体文字放置在txt文件中,我们通过下面的代码进行读取:
# 获取需要评论的文本内容
txt_contents=[]
f=open("回帖文案.txt", "r", encoding='utf-8')
line=f.readline() # 读取第一行
while line:
if line.strip() !="":
txt_contents.append(line.strip()) # 列表增加
line=f.readline() # 读取下一行
print(txt_contents)
count=len(txt_contents)
假如,我们是需要参加游戏论坛的盖楼评论活动,那么就可以用下面的文本进行随机提取评论,样本越多,重复性越少。
一般来说,这种经常有活动的网站都是需要验证登录的。而各个网站的验证码算法都不相同,怎么自动登录账号,往往就非常关键了。
对于识别验证码,我们要么用百度,腾讯,阿里云提供的文字识别接口,但是博主试过了都无法保证百分百识别成功,而且最高识别准备率都不到50%。
如果需要自己写机器学习识别算法,那么学过机器学习的都应该知道,这个是需要庞大的标记的,哪怕你真的做出来,恐怕人家网站又会换了验证方式。
这种验证码与防验证码一直在进步,花费大量实现标注验证码这些内容,往往会浪费大量的时间,到最后人家可能又换了。
所以,博主的建议还是自己手动输入验证码,也就这一步输入验证码手动,其他的全自动。完整代码如下:
import random
import time
from selenium import webdriver
import requests
import re
# 获取需要评论的文本内容
txt_contents=[]
f=open("回帖文案.txt", "r", encoding='utf-8')
line=f.readline() # 读取第一行
while line:
if line.strip() !="":
txt_contents.append(line.strip()) # 列表增加
line=f.readline() # 读取下一行
print(txt_contents)
count=len(txt_contents)
# 获取需要评论的所有网页链接
url_start="https://club.hihonor.com/cn/forum.php?mod=post&action=reply&fid=4515&tid="
url_end="&extra=page%3D1&replysubmit=yes&infloat=yes&handlekey=fastpost&inajax=1"
url=[] # 评论网页
txt_url=[] # 提供的网页(格式不同)
f=open("随机帖子.txt", "r", encoding='utf-8')
line=f.readline() # 读取第一行
while line:
if re.match(r'http[s]?://(?:[a-zA-Z]|[0-9]|[$-_@.&+]|[!*\(\),]|(?:%[0-9a-fA-F][0-9a-fA-F]))+', line):
txt_url.append(line.strip()) # 列表增加
line=f.readline() # 读取下一行
datas=[]
headers=[]
for i in txt_url:
url_start="https://club.hihonor.com/cn/forum.php?mod=post&action=reply&fid=4515&tid="
url_end="&extra=page%3D1&replysubmit=yes&infloat=yes&handlekey=fastpost&inajax=1"
url.append(url_start + i.split("-")[1] + url_end)
# 获取账号
usernames=[]
f=open("账号.txt", "r", encoding='utf-8')
line=f.readline() # 读取第一行
while line:
usernames.append(line.strip()) # 列表增加
line=f.readline() # 读取下一行
for name in usernames:
browser=webdriver.Chrome()
browser.implicitly_wait(10)
browser.get("https://club.hihonor.com/cn/")
time.sleep(5)
login_text=browser.find_element_by_xpath("//*[@id='loginandreg']/a[1]")
login_text.click()
username=browser.find_element_by_xpath(
'/html/body/div[1]/div[2]/div/div/div[1]/div[3]/span/div[1]/span/div[2]/div[2]/div/input')
password=browser.find_element_by_xpath(
'/html/body/div[1]/div[2]/div/div/div[1]/div[3]/span/div[1]/span/div[3]/div/div/div/input')
username.send_keys(name)
password.send_keys("密码")#所有盖楼刷评论账号密码尽量统一,这样就可以只在txt每行输入账号即可
sign=browser.find_element_by_xpath(
'/html/body/div[1]/div[2]/div/div/div[1]/div[3]/span/div[1]/span/div[6]/div/div/span/span')
#等待10秒,让程序运行者输入验证码
time.sleep(10)
sign.click()
time.sleep(2)
cookie=[item["name"] + "=" + item["value"] for item in browser.get_cookies()]
cookiestr=';'.join(item for item in cookie)
url2="https://club.hihonor.com/cn/thread-26183971-1-1.html"
time.sleep(2)
browser.get(url2)
posttime=browser.find_element_by_id("posttime")
posttime=posttime.get_attribute("value")
formhash=browser.find_element_by_name("formhash")
formhash=formhash.get_attribute("value")
browser.close()
data={
"formhash": formhash,
"posttime": posttime,
"usesig": "1",
"message": txt_contents[0],
}
header={
"accept": "application/json, text/javascript, */*; q=0.01",
"Accept-Encoding": "gzip, deflate, br",
"Accept-Language": "zh-CN,zh;q=0.9",
"Content-Length": "146",
"sec-ch-ua": '"Google Chrome";v="87", "\"Not;A\\Brand";v="99", "Chromium";v="87"',
"User-Agent": "Mozilla/5.0 (Linux; Android 6.0; Nexus 5 Build/MRA58N) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.141 Mobile Safari/537.36",
"Cookie": cookiestr,
"Content-Type": "application/x-www-form-urlencoded; charset=UTF-8",
"X-Requested-With": "XMLHttpRequest",
}
datas.append(data)
headers.append(header)
while True:
z=0
if int(time.strftime("%H%M%S")) <=220000:
url_num=random.sample(range(0, len(url)), len(url))
for i in url_num:
j=1
for data, header in zip(datas, headers):
data['message']=txt_contents[random.randint(0, count - 1)]
res=requests.post(url=url[i], data=data, headers=header)
if '回复发布成功' in res.text:
print("账号{0}回复成功".format(j))
else:
print(res.text)
j +=1
z +=1
time.sleep(5)
print("已经评论{0}条".format(str(z)))
如上面代码所示,我们的账号也是用txt文件统一处理的,这样可以达到多个账号同时刷的目的,当然一般网站获奖都不能是同一个IP,这里读者可以通过代理来处理。
其实登录后,随便一个帖子都有posttime与formhash两个值,只要你随机打开一个帖子(url2)就可以通过爬虫知识获取。
运行效果如头图所示。
*请认真填写需求信息,我们会在24小时内与您取得联系。