我和朋友正试图在我们频繁出现的棒球博客上计算一些评论指标(有多少用户评论某些帖子,评论谁,每个用户添加了多少条评论等)。
我对网页编程或抓取知之甚少,但我知道一些Python,所以我自愿提供帮助(她正在复制并将评论粘贴到.txt文件中并使用 Cmd + F来记录评论)。
我的初始方法使用了urllib2和BeautifulSoup(Python 2.7):
import sys,re,csv,glob,os
from collections import Counter
import urllib2
from bs4 import BeautifulSoup
url = "http://www.royalsreview.com/2016/6/8/11881484/an-analysis-of-rr-game-threads#comments"
f = urllib2.urlopen(url).read()
soup = BeautifulSoup(f)
userlist = soup.find_all("div", class_="comment")
通过在Chrome浏览器中访问该网址并点击" Inspect"我有点了解我要查找的内容。在评论中,它向我展示了我需要记录评论的HTML位。
但是,当我使用urllib2读取URL时,它提取的HTML不包含该网页上的注释。
从我的研究中,我认为这是因为urllib2将从服务器获取页面的来源,但它不会包含JavaScript生成的内容(我冒险来自我舒适的地方,这里)或其他什么(例如评论)。
如何通过添加评论来获取用户更改后的页面?
感谢您的帮助
答案 0 :(得分:1)
您可以通过向http://www.royalsreview.com/comments/load_comments/11645525
发送获取请求,以 json 格式获取数据:
import requests
from collections import Counter
from operator import itemgetter
url = "http://www.royalsreview.com/comments/load_comments/11645525"
js = requests.get(url).json()
cn = Counter(map(itemgetter("username"), js["comments"]))
print(cn)
这给了你:
Counter({u'artzfreak': 20, u'RoyallyDisplaced': 9, u'sterlingice': 8, u'Max Rieper': 6, u'Scott McKinney': 6, u'Cody.McElroy': 3, u'GrassyKnoll': 3, u'Farmhand': 3, u'Minda Haas Kuhlmann': 3, u'Warden11': 2, u'nom nom nom de plume': 2, u'1040X': 2, u'Nighthawk at the Diner': 2, u'thelaundry': 2, u'Gopherballs': 2, u"Daenerys C. O'sFanaryen": 1, u'Shaun Newkirk': 1, u'Blue and Red': 1, u'wcgrad': 1, u'MrAndersonmm': 1, u'DCChiefFan': 1, u'J.K. Ward': 1, u'philofthenorth': 1, u'Mink Farmer': 1, u'keith jersey': 1, u'Kevin Ruprecht': 1, u'Tim Webber': 1, u'Matthew LaMar': 1, u'MightyMinx': 1, u'Quisenberry4Ever': 1, u'Daloath': 1, u'HalsHatsCrooked': 1, u'pete_clarf': 1})
如果您打印js["comments"]
,您会看到一系列代码:
{u'ancestry': u'0379481445',
u'bad_flags_count': 0,
u'body': u'<blockquote>So maybe it\u2019s as hunter s. royal suggested, and it\u2019s because philofthenorth got a job.</blockquote>',
u'created_on': u'2016-06-08T17:35:09.000Z',
u'created_on_long': u'Jun 8, 2016 | 1:35 PM',
u'created_on_short': u'06.08.16 1:35pm',
u'created_on_timestamp': 1465407309,
u'depth': 1,
u'entry_id': 11645525,
u'hidden': False,
u'id': 379481445,
u'inappropriate_flags_count': 0,
u'parent_id': None,
u'permalink': u'/2016/6/8/11881484/an-analysis-of-rr-game-threads/comment/379481445',
u'recommended_flags_count': 5,
u'shortlink': u'/c/379481445',
u'signature': u'',
u'spam_flags_count': 0,
u'title': u'Love it',
u'troll_flags_count': 0,
u'user_id': 153964,
u'username': u'sterlingice',
u'version': 1}
每条评论都有自己的词典,并保留上述所有信息。
要不必硬编码 entry_id ,e可以从实际页面解析它,然后将其传递到:
import requests
from collections import Counter
from operator import itemgetter
init_url = "http://www.royalsreview.com/2016/6/8/11881484/an-analysis-of-rr-game-threads#comments"
url = "http://www.royalsreview.com/comments/load_comments/{}"
entry_id = BeautifulSoup(requests.get(init_url).content).select_one("h2.m-entry__title")["data-remote-admin-entry-id"]
print(entry_id)
js = requests.get(url.format(entry_id)).json()
cn = Counter(map(itemgetter("username"), js["comments"]))
print(cn)
所以不需要任何javascript,你可以在格式良好的json中获得所有数据。
答案 1 :(得分:0)
使用Selenium或Dryscape。 Selenium打开了一个Web浏览器,你实际上可以看到它做的事情。由于使用了浏览器,它也会呈现Javascript。
我注意到页面来源中显示的评论数量。
<span class="comments-count">80</span>
您可以抓取此范围以获取评论数量。你可以在不同的时间点抓住这个范围,看是否有新评论(人们不太可能删除评论)
以下是使用Selenium抓取它的代码。
from selenium import webdriver
driver = webdriver.Firefox() # Opens firefox
driver.get('http://www.royalsreview.com/2016/6/8/11881484/an-analysis-of-rr-game-threads#comments')
userlist = driver.find_elements_by_class_name('comment')
# ^ Finds all elements with the class comment and stores it in a list
# userlist is a list of all the tags with the class comment
print userlist[0].text
上面的print语句给出了(页面中的第一条评论)。
喜欢它 也许这就像猎人一样。皇室建议,这是因为philofthenorth得到了一份工作。 来自Sterlingice于2016年6月8日|下午1:35回复
使用userlist [1] .text打印第二条评论,依此类推。
我建议你使用
print len(userlist)
与页面上的评论数量交叉引用。该页面显示有80条评论,但用户列表的长度为82.请务必交叉检查。
如果您有任何疑问,请告诉我们:)
答案 2 :(得分:0)
我最终做了什么:
import sys,re,csv,glob,os
from collections import Counter
import dryscrape
from bs4 import BeautifulSoup
url = "http://www.royalsreview.com/2016/6/8/11881484/an-analysis-of-rr-game-threads#comments"
session = dryscrape.Session()
session.visit(url)
f = session.body()
soup = BeautifulSoup(f)
posterSoup = soup.find_all("a", class_="poster")
posterList = []
for poster in posterSoup:
posterList.append(poster.string.lstrip())
posterCount = Counter(posterList)
with open('metrics.txt', 'w') as out:
for entry in posterCount:
out.write(entry + "\t" + str(posterCount[entry]) + "\n")
我真正想要的是每张海报提交的评论数量。因此,我删除了所有注释,将它们放入列表中,并使用Counter将该列表折叠到计数器容器中。然后,我可以打印出海报的用户名,然后打印该用户提供的评论数量。