python—我如何从这个网站上获取特定的数据,这些数据';什么在不断变化/更新?
网址为: 目前,我的代码如下:python—我如何从这个网站上获取特定的数据,这些数据';什么在不断变化/更新?,python,web-scraping,beautifulsoup,request,Python,Web Scraping,Beautifulsoup,Request,网址为: 目前,我的代码如下: from bs4 import BeautifulSoup import requests import re site = 'https://pokemongo.gamepress.gg/best-attackers-type' page_data = requests.get(site, headers=headers) soup = BeautifulSoup(page_data.text, 'html.parser') check_gamepres
from bs4 import BeautifulSoup
import requests
import re
site = 'https://pokemongo.gamepress.gg/best-attackers-type'
page_data = requests.get(site, headers=headers)
soup = BeautifulSoup(page_data.text, 'html.parser')
check_gamepress = soup.body.findAll(text=re.compile("Strength"))
print(check_gamepress)
然而,我真的很想搜集某些数据,我真的遇到了麻烦。
例如,我将如何刮除显示以下内容的部分以获得最佳错误类型:
"Good typing and lightning-fast attacks. Though cool-looking, Scizor is somewhat fragile."
当一个更好的口袋妖怪出现时,这些信息显然可以像过去一样更新。那么,我如何在将来可能会更新的地方刮取这些数据,而不必在发生这种情况时进行代码更改呢
提前感谢您的阅读 由于HTML的组织方式,这个特定的站点有点困难。包含信息的相关标签实际上没有很多区别特征,因此我们必须稍微聪明一点。使事情复杂化的是,包含整个页面信息的div是同级的。我们还必须用一些独创性来弥补这种网页设计的滑稽 我确实注意到了一种模式,这种模式在整个页面中(几乎完全)是一致的。每个“类型”和基础部分分为3个部分:
- 包含类型和口袋妖怪的div,例如
黑暗类型:暴君
- 包含“专业”和移动的div
- 包含“评级”和评论的div
import re
import json
import requests
from pprint import pprint
from bs4 import BeautifulSoup
def type_section(tag):
"""Find the tags that has the move type and pokemon name"""
pattern = r"[A-z]{3,} Type: [A-z]{3,}"
# if all these things are true, it should be the right tag
return all((tag.name == 'div',
len(tag.get('class', '')) == 1,
'field__item' in tag.get('class', []),
re.findall(pattern, tag.text),
))
def parse_type_pokemon(tag):
"""Parse out the move type and pokemon from the tag text"""
s = tag.text.strip()
poke_type, pokemon = s.split(' Type: ')
return {'type': poke_type, 'pokemon': pokemon}
def parse_speciality(tag):
"""Parse the tag containing the speciality and moves"""
table = tag.find('table')
rows = table.find_all('tr')
speciality_row, fast_row, charge_row = rows
speciality_types = []
for anchor in speciality_row.find_all('a'):
# Each type 'badge' has a href with the type name at the end
href = anchor.get('href')
speciality_types.append(href.split('#')[-1])
fast_move = fast_row.find('td').text
charge_move = charge_row.find('td').text
return {'speciality': speciality_types,
'fast_move': fast_move,
'charge_move': charge_move}
def parse_rating(tag):
"""Parse the tag containing categorical ratings and commentary"""
table = tag.find('table')
category_tags = table.find_all('th')
strength_tag, meta_tag, future_tag = category_tags
str_rating = strength_tag.parent.find('td').text.strip()
meta_rating = meta_tag.parent.find('td').text.strip()
future_rating = meta_tag.parent.find('td').text.strip()
blurb_tags = table.find_all('td', {'colspan': '2'})
if blurb_tags:
# `if` to accomodate fire section bug
str_blurb_tag, meta_blurb_tag, future_blurb_tag = blurb_tags
str_blurb = str_blurb_tag.text.strip()
meta_blurb = meta_blurb_tag.text.strip()
future_blurb = future_blurb_tag.text.strip()
else:
str_blurb = None;meta_blurb=None;future_blurb=None
return {'strength': {
'rating': str_rating,
'commentary': str_blurb},
'meta': {
'rating': meta_rating,
'commentary': meta_blurb},
'future': {
'rating': future_rating,
'commentary': future_blurb}
}
def extract_divs(tag):
"""
Get the divs containing the moves/ratings
determined based on sibling position from the type tag
"""
_, speciality_div, _, rating_div, *_ = tag.next_siblings
return speciality_div, rating_div
def main():
"""All together now"""
url = 'https://pokemongo.gamepress.gg/best-attackers-type'
response = requests.get(url)
soup = BeautifulSoup(response.text, 'lxml')
types = {}
for type_tag in soup.find_all(type_section):
type_info = {}
type_info.update(parse_type_pokemon(type_tag))
speciality_div, rating_div = extract_divs(type_tag)
type_info.update(parse_speciality(speciality_div))
type_info.update(parse_rating(rating_div))
type_ = type_info.get('type')
types[type_] = type_info
pprint(types) # We did it
with open('pokemon.json', 'w') as outfile:
json.dump(types, outfile)
目前,整件事只有一个小问题。还记得我说过这个模式几乎是完全一致的吗?嗯,Fire
类型在这里是一个奇怪的球,因为它包含了两个pokemon,所以Fire
类型的结果是不正确的。我或一些勇敢的人可能会想出一个办法来解决这个问题。或者他们将来会选择一个火精灵
这段代码、生成的json(经过修饰)和所用HTML响应的存档可以在中找到。太宽泛的问题。您可以尝试保存页面并检查差异。看看这个列表是否有其他格式:rss、json、xml。@LuisMuñoz我只是想知道如何首先提取这些数据,正确的方法是什么?如果我每次都要更新我的机器人,我想这很好,但我肯定更想知道如何刮去那部分,我会简单地用那句话的一部分来更改“强度”,还是有办法使用html标记来找到它?你可以试着写一个基于Xpath的解析器。此XPath将获得具有field\u item class:'//div[@class=“field\u item]的所有div标记的列表“。解析列表并保存为cvs或其他格式,然后使用它与将来的版本进行比较。如果您真的感兴趣,这不是一个很好的项目:)。@LuisMuñoz感谢您的快速回复!感谢您的帮助。是的,我正在研究这个问题,并使用beautifulsoup搜索“field_uu”项目“同样,但该页面上的几乎所有内容都使用了该标记,因此它返回了大量信息,有没有办法进一步获取我正在查找的确切数据?我在discord上运行一个机器人,基本上,每次有人输入时!数据水,我想机器人拉所有的信息,它可以关于最好的水类型。现在,我的机器人只能提供最好的口袋妖怪。@sytech这么认为!我想我可能只是做错了什么。难道所有“优势”的模式都不一样吗?我想我只能用汤了。身体。再找一次。非常感谢。非常感谢您的精彩解释!至于火的类型,我的机器人在创建嵌入时也遇到了问题,我做了类似的事情来解决这个问题:cut_gamepress_furth=cut_gamepress.split('&'),然后打印(cut_gamepress_furth[0]。可能现在需要修改我的所有代码,以便与您的解释相匹配。再次感谢您!)解释得很好,做得很完美!不用担心@sb2894。如果您对代码中的细节有任何疑问,请发表评论。干杯,欢迎来到SO!很高兴终于来到这里!最近刚开始自学Python 3,我对这个社区是多么棒感到震惊!