优化我的 Python 抓取工具
Optimizing my Python Scraper
有点啰嗦的问题,我可能只需要有人给我指出正确的方向。我正在构建一个网络抓取工具来从 ESPN 的网站上获取篮球运动员的信息。 URL 结构非常简单,因为每个球员卡在 URL 中都有一个特定的 id。为了获取信息,我正在编写一个从 1-~6000 的循环来从他们的数据库中抓取玩家。我的问题是是否有更有效的方法来做到这一点?
from bs4 import BeautifulSoup
from urllib2 import urlopen
import requests
import nltk
import re
age = [] # Empty List to store player ages
BASE = 'http://espn.go.com/nba/player/stats/_/id/' # Base Structure of Player Card URL
def get_age(BASE): #Creates a function
#z = range(1,6000) # Create Range from 1 to 6000
for i in range(1, 6000): # This is a for loop
BASE_U = BASE + str(i) + '/' # Create URL For Player
r = requests.get(BASE_U)
soup = BeautifulSoup(r.text)
#Prior to this step, I had to print out the soup object and look through the HTML in order to find the tag that contained my desired information
# Get Age of Players
age_tables = soup.find_all('ul', class_="player-metadata") # Grabs all text in the metadata tag
p = str(age_tables) # Turns text into a string
#At this point I had to look at all the text in the p object and determine a way to capture the age info
if "Age: " not in p: # PLayer ID doesn't exist so go to next to avoid error
continue
else:
start = p.index("Age: ") + len("Age: ") # Gets the location of the players age
end = p[start:].index(")") + start
player_id.append(i) #Adds player_id to player_id list
age.append(p[start:end]) # Adds player's age to age list
get_age(BASE)
任何帮助,即使是很小的帮助,我们都将不胜感激。即使它只是为我指明了正确的方向,也不一定是直接的解决方案
谢谢,
本
就像网络安全中的端口扫描器,多线程会大大加快你的编程速度。
不仅更高效,而且更有条理和可扩展的方法将涉及切换到 Scrapy
网络抓取框架。
您遇到的主要性能问题是因为您当前方法的 "blocking" 性质 - Scrapy
会立即解决它box,因为它基于 twisted
并且是完全异步的。
我可能会从 http://espn.go.com/nba/players 开始并使用以下正则表达式来获取团队花名册 URLs...
\href="(/nba/teams/roster\?team=[^"]+)">([^<]+)</a>\
然后我会得到结果匹配组,其中 \1 是 URL 的最后一部分,\2 是团队名称。然后我会使用那些 URLs 来抓取每个团队花名册页面以寻找玩家 URLs...
\href="(http://espn.go.com/nba/player/_/id/[^"]+)">([^<]+)</a>\
我终于得到了结果匹配组,其中 \1 是播放器页面的 URL,\2 是播放器名称。我会抓取每个结果 URL 以获得我需要的信息。
正则表达式是炸弹。
希望对您有所帮助。
有点啰嗦的问题,我可能只需要有人给我指出正确的方向。我正在构建一个网络抓取工具来从 ESPN 的网站上获取篮球运动员的信息。 URL 结构非常简单,因为每个球员卡在 URL 中都有一个特定的 id。为了获取信息,我正在编写一个从 1-~6000 的循环来从他们的数据库中抓取玩家。我的问题是是否有更有效的方法来做到这一点?
from bs4 import BeautifulSoup
from urllib2 import urlopen
import requests
import nltk
import re
age = [] # Empty List to store player ages
BASE = 'http://espn.go.com/nba/player/stats/_/id/' # Base Structure of Player Card URL
def get_age(BASE): #Creates a function
#z = range(1,6000) # Create Range from 1 to 6000
for i in range(1, 6000): # This is a for loop
BASE_U = BASE + str(i) + '/' # Create URL For Player
r = requests.get(BASE_U)
soup = BeautifulSoup(r.text)
#Prior to this step, I had to print out the soup object and look through the HTML in order to find the tag that contained my desired information
# Get Age of Players
age_tables = soup.find_all('ul', class_="player-metadata") # Grabs all text in the metadata tag
p = str(age_tables) # Turns text into a string
#At this point I had to look at all the text in the p object and determine a way to capture the age info
if "Age: " not in p: # PLayer ID doesn't exist so go to next to avoid error
continue
else:
start = p.index("Age: ") + len("Age: ") # Gets the location of the players age
end = p[start:].index(")") + start
player_id.append(i) #Adds player_id to player_id list
age.append(p[start:end]) # Adds player's age to age list
get_age(BASE)
任何帮助,即使是很小的帮助,我们都将不胜感激。即使它只是为我指明了正确的方向,也不一定是直接的解决方案
谢谢, 本
就像网络安全中的端口扫描器,多线程会大大加快你的编程速度。
不仅更高效,而且更有条理和可扩展的方法将涉及切换到 Scrapy
网络抓取框架。
您遇到的主要性能问题是因为您当前方法的 "blocking" 性质 - Scrapy
会立即解决它box,因为它基于 twisted
并且是完全异步的。
我可能会从 http://espn.go.com/nba/players 开始并使用以下正则表达式来获取团队花名册 URLs...
\href="(/nba/teams/roster\?team=[^"]+)">([^<]+)</a>\
然后我会得到结果匹配组,其中 \1 是 URL 的最后一部分,\2 是团队名称。然后我会使用那些 URLs 来抓取每个团队花名册页面以寻找玩家 URLs...
\href="(http://espn.go.com/nba/player/_/id/[^"]+)">([^<]+)</a>\
我终于得到了结果匹配组,其中 \1 是播放器页面的 URL,\2 是播放器名称。我会抓取每个结果 URL 以获得我需要的信息。
正则表达式是炸弹。
希望对您有所帮助。