如何解决整个页面都没有用Beautiful Soup解析
我能够从所需的网站中检索到前19条记录以外的任何内容。鉴于该网站上的列表是动态的,我认为这可能与我运行python代码时仅返回前19个信息有关。我已经在线阅读了一些书,但是没有找到解决我问题的方法。
下面是我的完整python代码。我很乐意得到社区的意见,以解决该问题。
import requests
from requests import get
from bs4 import BeautifulSoup
import pandas as pd
import numpy as np
import csv
headers = {"Accept-Language": "en-US,en;q=0.5"}
url = "https://www.producthunt.com/time-travel/2019/1/7"
results = requests.get(url,headers=headers)
soup = BeautifulSoup(results.text,"html.parser")
name = []
description = []
category = []
up_votes = []
ph_project_div = soup.find_all('div',class_='item_54fdd')
for container in ph_project_div:
ph_name = container.a.find('h3',class_='font_9d927 medium_51d18 semiBold_e201b title_9ddaf lineHeight_042f1 underline_57d3c').text
name.append(ph_name)
ph_desc = container.a.find('p',class_='font_9d927 grey_bbe43 small_231df normal_d2e66 tagline_619b7 lineHeight_042f1 underline_57d3c').text
description.append(ph_desc)
ph_cat = container.find('span',class_='font_9d927 grey_bbe43 xSmall_1a46e lineHeight_042f1 underline_57d3c')
category.append(ph_cat)
ph_vote = container.find('span',class_='font_9d927 small_231df semiBold_e201b lineHeight_042f1 underline_57d3c')
up_votes.append(ph_vote)
phunt = pd.DataFrame({
'Product Name': name,'Product Description': description,'Product Category': category,'Product Votes': up_votes,})
phunt.to_csv("ph_01_04_2019.csv")
解决方法
因此,您使用JavaScript获取下一组帖子是正确的。这是滚动事件触发对服务器的HTTP请求的示例。
要查看此信息,可以使用检查页面->网络工具-> XHR。清除所有请求并向下滚动。您会看到发出了发布请求,并且在右侧会看到数据。我倾向于搜索我希望看到的内容以确认数据是否存在。
有两种方法可以处理这种动态内容。
- 模仿HTTP请求
- 使用浏览器活动来获取数据
第一个总是更好的选择,如果有可能存在API标记点等,那么最好使用它。数据的效率和准确性很重要。
第二个选项依赖于诸如selenium之类的软件包,它们速度较慢,对HTML的更改可能非常脆弱,从而使代码烦人。
要收集以下代码的信息,我复制了在网络工具的XHR部分中找到的请求的cURL。我使用的网站将其转换为python格式,例如curl.trillworks.com。
HTTP请求可能只需要一个简单的get请求即可到达端点的正确url,在必须输入标头/参数/数据之前,首先这样做总是一件好事。在此示例中,您将获得全部三个信息,但实际上您只需要一个用户代理和所需的响应对象类型以及用于将您引导至正确响应的数据。
代码示例
import requests
headers = {
'User-Agent': 'M','content-type': 'application/json',}
data = '{"operationName":"Posts","variables":{"year":2019,"month":1,"day":7,"cursor":"MjA=","includeLayout":false},"query":"query Posts($year: Int,$month: Int,$day: Int,$cursor: String) {\\n posts(first: 20,year: $year,month: $month,day: $day,after: $cursor) {\\n edges {\\n node {\\n id\\n ...PostItemList\\n __typename\\n }\\n __typename\\n }\\n pageInfo {\\n endCursor\\n hasNextPage\\n __typename\\n }\\n __typename\\n }\\n}\\n\\nfragment PostItemList on Post {\\n id\\n ...PostItem\\n __typename\\n}\\n\\nfragment PostItem on Post {\\n id\\n _id\\n comments_count\\n name\\n shortened_url\\n slug\\n tagline\\n updated_at\\n ...CollectButton\\n ...PostThumbnail\\n ...PostVoteButton\\n ...TopicFollowButtonList\\n __typename\\n}\\n\\nfragment CollectButton on Post {\\n id\\n name\\n isCollected\\n __typename\\n}\\n\\nfragment PostThumbnail on Post {\\n id\\n name\\n thumbnail {\\n id\\n media_type\\n ...MediaThumbnail\\n __typename\\n }\\n ...PostStatusIcons\\n __typename\\n}\\n\\nfragment MediaThumbnail on Media {\\n id\\n image_uuid\\n __typename\\n}\\n\\nfragment PostStatusIcons on Post {\\n name\\n product_state\\n __typename\\n}\\n\\nfragment PostVoteButton on Post {\\n _id\\n id\\n featured_at\\n updated_at\\n disabled_when_scheduled\\n has_voted\\n ... on Votable {\\n id\\n votes_count\\n __typename\\n }\\n __typename\\n}\\n\\nfragment TopicFollowButtonList on Topicable {\\n id\\n topics {\\n edges {\\n node {\\n id\\n ...TopicFollowButton\\n __typename\\n }\\n __typename\\n }\\n __typename\\n }\\n __typename\\n}\\n\\nfragment TopicFollowButton on Topic {\\n id\\n slug\\n name\\n isFollowed\\n ...TopicImage\\n __typename\\n}\\n\\nfragment TopicImage on Topic {\\n name\\n image_uuid\\n __typename\\n}\\n"}'
response = requests.post('https://www.producthunt.com/frontend/graphql',headers=headers,data=data)
data = response.json()
for a in response.json()['data']['posts']['edges']:
name = a['node']['name']
subtext = a['node']['tagline']
votes = a['node']['votes_count']
category = a['node']['topics']['edges'][0]['node']['name']
print('-'*20)
print('Name: ',name)
print('Tagline: ',subtext)
print('Category: ',category)
print('Votes: ',votes)
输出
--------------------
Name: Newbook Models
Tagline: Find & book fashion models online
Category: Productivity
Votes: 57
--------------------
Name: 3Leaf Edibles - Quinoa Granola Bite
Tagline: Vegan,low dose,high quality edibles.
Category: Health and Fitness
Votes: 57
--------------------
Name: Payfacile
Tagline: We simplify access to online payment.
Category: Fintech
Votes: 43
--------------------
Name: Halo by Motorola
Tagline: Watch over your baby from above
Category: Kids
Votes: 27
--------------------
Name: Bowflex Max Intelligence
Tagline: Bring the benefits of a personal trainer to your home
Category: Health and Fitness
Votes: 23
解释
标题,您无需指定user-agent
,任何操作都可以,因此我只使用了一个字符。尽管content-type
是必需的,但您通过试用发现这是一个错误。
我不会撒谎的数据我没有心去尝试分解,我猜是交替进行可能最终不会为您提供所需的数据。关于此数据的好处之一是,您可以更改年/月/日,它将为您提供该页面的数据,该页面需要滚动才能触发项目。
您没有特别询问这个问题,但是使用诸如f字符串之类的方法来为每个请求输入特定数据。get()调用将是解决此问题的方法。
现在您得到的是一个json对象,方法response.json()
将该对象转换为python字典。因此,可以使用归因于字典的所有方法。
我强烈建议您查看response.json()
词典,除非您这样做,否则您将不会真正看到名称subtext的含义。但是大多数json对象是嵌套数据集,因此在这种情况下,您通常需要的数据位于许多键的后面。对于我发布的每条帖子,我都会四处寻找名字/标语。
response.json()['data'] ['posts'] ['edges']列表项的典型输出
{'node': {'id': '142398','__typename': 'Post','_id': 'UG9zdC0xNDIzOTg=','comments_count': 9,'name': 'dinely','shortened_url': '/r/p/142398','slug': 'dinely','tagline': 'Up to 50% off top restaurants,no coupon needed','updated_at': '2020-04-28T16:55:48-07:00','topics': {'edges': [{'node': {'id': '2','__typename': 'Topic','slug': 'android','name': 'Android','isFollowed': False,'image_uuid': 'd3e235c7-437b-4ed1-8298-2ce04eded455'},'__typename': 'TopicEdge'},{'node': {'id': '8','slug': 'iphone','name': 'iPhone','image_uuid': '0ee71650-973d-4933-a3eb-c7201950db4b'},{'node': {'id': '159','slug': 'drinking','name': 'Drinking','image_uuid': '33a0c652-253d-491f-b86b-4e9ba32ee203'},{'node': {'id': '250','slug': 'travel','name': 'Travel','image_uuid': '0a49cae9-ccff-47f1-8998-d0f47c2e7775'},{'node': {'id': '278','slug': 'e-commerce','name': 'E-Commerce','image_uuid': '1aa939fc-89dd-49ae-9fde-d456f9a6c8d2'},'__typename': 'TopicEdge'}],'__typename': 'TopicConnection'},'featured_at': '2019-01-07T03:52:19-08:00','disabled_when_scheduled': True,'has_voted': False,'votes_count': 58,'thumbnail': {'id': '703734','media_type': 'image','__typename': 'Media','image_uuid': '96893366-45e6-477e-9bb8-0e04c2070da6'},'product_state': 'default','isCollected': False},'__typename': 'PostEdge'}
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。