Skip to content

Commit

Permalink
Merge pull request #547 from Terseus/prevent-301
Browse files Browse the repository at this point in the history
Prevent 301
  • Loading branch information
emlazzarin authored Nov 12, 2022
2 parents 63b5c68 + 022e5a9 commit 0d6113a
Show file tree
Hide file tree
Showing 25 changed files with 19,422 additions and 20,544 deletions.
2 changes: 1 addition & 1 deletion CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ pandas/_libs/testing.pyx:168: AssertionError

# Check the returned response and see if it contains valid data.
# We can use the following values to update our test and make it pass.
(Pdb) df_expected.to_dict(orient='list')
(Pdb) df_result.to_dict(orient='list')
{'pizza': [100, 87, 78, 51, 52], 'bagel': [2, 2, 2, 1, 1], 'isPartial': [False, False, False, False, False]}
```

Expand Down
32 changes: 15 additions & 17 deletions pytrends/request.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,4 @@
import json
import sys
import time
from datetime import datetime, timedelta

import pandas as pd
import requests
Expand All @@ -15,22 +12,25 @@
from urllib.parse import quote


BASE_TRENDS_URL = 'https://trends.google.com/trends'


class TrendReq(object):
"""
Google Trends API
"""
GET_METHOD = 'get'
POST_METHOD = 'post'
GENERAL_URL = 'https://trends.google.com/trends/api/explore'
INTEREST_OVER_TIME_URL = 'https://trends.google.com/trends/api/widgetdata/multiline'
INTEREST_BY_REGION_URL = 'https://trends.google.com/trends/api/widgetdata/comparedgeo'
RELATED_QUERIES_URL = 'https://trends.google.com/trends/api/widgetdata/relatedsearches'
TRENDING_SEARCHES_URL = 'https://trends.google.com/trends/hottrends/visualize/internal/data'
TOP_CHARTS_URL = 'https://trends.google.com/trends/api/topcharts'
SUGGESTIONS_URL = 'https://trends.google.com/trends/api/autocomplete/'
CATEGORIES_URL = 'https://trends.google.com/trends/api/explore/pickers/category'
TODAY_SEARCHES_URL = 'https://trends.google.com/trends/api/dailytrends'
REALTIME_TRENDING_SEARCHES_URL = 'https://trends.google.com/trends/api/realtimetrends'
GENERAL_URL = f'{BASE_TRENDS_URL}/api/explore'
INTEREST_OVER_TIME_URL = f'{BASE_TRENDS_URL}/api/widgetdata/multiline'
INTEREST_BY_REGION_URL = f'{BASE_TRENDS_URL}/api/widgetdata/comparedgeo'
RELATED_QUERIES_URL = f'{BASE_TRENDS_URL}/api/widgetdata/relatedsearches'
TRENDING_SEARCHES_URL = f'{BASE_TRENDS_URL}/hottrends/visualize/internal/data'
TOP_CHARTS_URL = f'{BASE_TRENDS_URL}/api/topcharts'
SUGGESTIONS_URL = f'{BASE_TRENDS_URL}/api/autocomplete/'
CATEGORIES_URL = f'{BASE_TRENDS_URL}/api/explore/pickers/category'
TODAY_SEARCHES_URL = f'{BASE_TRENDS_URL}/api/dailytrends'
REALTIME_TRENDING_SEARCHES_URL = f'{BASE_TRENDS_URL}/api/realtimetrends'
ERROR_CODES = (500, 502, 504, 429)

def __init__(self, hl='en-US', tz=360, geo='', timeout=(2, 5), proxies='',
Expand Down Expand Up @@ -69,8 +69,7 @@ def GetGoogleCookie(self):
if "proxies" in self.requests_args:
try:
return dict(filter(lambda i: i[0] == 'NID', requests.get(
'https://trends.google.com/?geo={geo}'.format(
geo=self.hl[-2:]),
f'{BASE_TRENDS_URL}/?geo={self.hl[-2:]}',
timeout=self.timeout,
**self.requests_args
).cookies.items()))
Expand All @@ -83,8 +82,7 @@ def GetGoogleCookie(self):
proxy = ''
try:
return dict(filter(lambda i: i[0] == 'NID', requests.get(
'https://trends.google.com/?geo={geo}'.format(
geo=self.hl[-2:]),
f'{BASE_TRENDS_URL}/?geo={self.hl[-2:]}',
timeout=self.timeout,
proxies=proxy,
**self.requests_args
Expand Down
1,543 changes: 752 additions & 791 deletions tests/cassettes/test_request/test_build_payload.yaml

Large diffs are not rendered by default.

1,465 changes: 713 additions & 752 deletions tests/cassettes/test_request/test_initial_data.yaml

Large diffs are not rendered by default.

1,594 changes: 778 additions & 816 deletions tests/cassettes/test_request/test_interest_by_region_city_resolution.yaml

Large diffs are not rendered by default.

1,657 changes: 809 additions & 848 deletions tests/cassettes/test_request/test_interest_by_region_ok.yaml

Large diffs are not rendered by default.

1,461 changes: 711 additions & 750 deletions tests/cassettes/test_request/test_interest_over_time_bad_gprop.yaml

Large diffs are not rendered by default.

1,563 changes: 762 additions & 801 deletions tests/cassettes/test_request/test_interest_over_time_froogle.yaml

Large diffs are not rendered by default.

1,563 changes: 762 additions & 801 deletions tests/cassettes/test_request/test_interest_over_time_images.yaml

Large diffs are not rendered by default.

1,369 changes: 665 additions & 704 deletions tests/cassettes/test_request/test_interest_over_time_news.yaml

Large diffs are not rendered by default.

1,563 changes: 762 additions & 801 deletions tests/cassettes/test_request/test_interest_over_time_ok.yaml

Large diffs are not rendered by default.

1,722 changes: 842 additions & 880 deletions tests/cassettes/test_request/test_interest_over_time_partial.yaml

Large diffs are not rendered by default.

1,369 changes: 665 additions & 704 deletions tests/cassettes/test_request/test_interest_over_time_youtube.yaml

Large diffs are not rendered by default.

6,891 changes: 3,307 additions & 3,584 deletions tests/cassettes/test_request/test_realtime_trending_searches_ok.yaml

Large diffs are not rendered by default.

1,619 changes: 790 additions & 829 deletions tests/cassettes/test_request/test_related_queries_result_keys.yaml

Large diffs are not rendered by default.

1,623 changes: 792 additions & 831 deletions tests/cassettes/test_request/test_related_queries_result_rising.yaml

Large diffs are not rendered by default.

1,623 changes: 792 additions & 831 deletions tests/cassettes/test_request/test_related_queries_result_top.yaml

Large diffs are not rendered by default.

1,447 changes: 704 additions & 743 deletions tests/cassettes/test_request/test_related_topics_result_keys.yaml

Large diffs are not rendered by default.

1,573 changes: 767 additions & 806 deletions tests/cassettes/test_request/test_related_topics_result_rising.yaml

Large diffs are not rendered by default.

1,573 changes: 767 additions & 806 deletions tests/cassettes/test_request/test_related_topics_result_top.yaml

Large diffs are not rendered by default.

1,473 changes: 717 additions & 756 deletions tests/cassettes/test_request/test_suggestions_ok.yaml

Large diffs are not rendered by default.

1,538 changes: 750 additions & 788 deletions tests/cassettes/test_request/test_tokens.yaml

Large diffs are not rendered by default.

1,471 changes: 716 additions & 755 deletions tests/cassettes/test_request/test_top_charts_ok.yaml

Large diffs are not rendered by default.

2,101 changes: 1,019 additions & 1,082 deletions tests/cassettes/test_request/test_trending_searches_ok.yaml

Large diffs are not rendered by default.

131 changes: 64 additions & 67 deletions tests/test_request.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
import responses
from pandas.testing import assert_frame_equal

from pytrends.request import TrendReq
from pytrends.request import TrendReq, BASE_TRENDS_URL


@dataclass
Expand Down Expand Up @@ -173,7 +173,7 @@ def test_interest_over_time_ok():
pytrend.build_payload(kw_list=['pizza', 'bagel'], timeframe='2021-01-01 2021-01-05')
df_result = pytrend.interest_over_time()
df_expected = build_interest_over_time_df({
'pizza': [100, 87, 78, 51, 52],
'pizza': [100, 84, 78, 50, 52],
'bagel': [2, 2, 2, 1, 1]
}, dates=['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05'])
assert_frame_equal(df_result, df_expected)
Expand All @@ -189,8 +189,8 @@ def test_interest_over_time_images():
)
df_result = pytrend.interest_over_time()
df_expected = build_interest_over_time_df({
'pizza': [82, 100, 89, 92, 92],
'bagel': [2, 2, 5, 5, 5],
'pizza': [83, 100, 89, 93, 93],
'bagel': [2, 2, 4, 4, 4]
}, dates=['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05'])
assert_frame_equal(df_result, df_expected)

Expand All @@ -205,8 +205,8 @@ def test_interest_over_time_news():
)
df_result = pytrend.interest_over_time()
df_expected = build_interest_over_time_df({
'pizza': [88, 66, 100, 32, 53],
'bagel': [0, 10, 10, 10, 0],
'pizza': [100, 51, 76, 44, 49],
'bagel': [0, 0, 0, 0, 15]
}, dates=['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05'])
assert_frame_equal(df_result, df_expected)

Expand All @@ -221,8 +221,8 @@ def test_interest_over_time_youtube():
)
df_result = pytrend.interest_over_time()
df_expected = build_interest_over_time_df({
'pizza': [93, 98, 100, 93, 98],
'bagel': [1, 2, 1, 2, 1],
'pizza': [88, 100, 99, 90, 93],
'bagel': [1, 1, 1, 2, 1]
}, dates=['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05'])
assert_frame_equal(df_result, df_expected)

Expand All @@ -237,8 +237,8 @@ def test_interest_over_time_froogle():
)
df_result = pytrend.interest_over_time()
df_expected = build_interest_over_time_df({
'pizza': [88, 100, 86, 57, 85],
'bagel': [0, 0, 0, 4, 0],
'pizza': [100, 100, 88, 61, 91],
'bagel': [7, 0, 4, 0, 0]
}, dates=['2021-01-01', '2021-01-02', '2021-01-03', '2021-01-04', '2021-01-05'])
assert_frame_equal(df_result, df_expected)

Expand Down Expand Up @@ -282,13 +282,13 @@ def test_interest_by_region_city_resolution():
expected_result = ExpectedResult(
length=200,
df_head=pd.DataFrame({
'pizza': [95, 97, 97],
'bagel': [5, 3, 3],
}, index=pd.Index(['Grafton', 'Raleigh', 'Philadelphia'], name='geoName')),
'pizza': [95, 96, 96],
'bagel': [5, 4, 4],
}, index=pd.Index(['Grafton', 'Melbourne', 'Boston'], name='geoName')),
df_tail=pd.DataFrame({
'pizza': [0, 0, 0],
'bagel': [0, 0, 0],
}, index=pd.Index(['Ahmedabad', 'Abu Dhabi', 'Aarhus'], name='geoName'))
}, index=pd.Index(['Andover', 'Anchorage', 'Allen'], name='geoName'))
)
expected_result.assert_equals(df_result)

Expand All @@ -315,17 +315,17 @@ def test_related_topics_result_top():
expected_result = ExpectedResult(
length=22,
df_head=pd.DataFrame({
'value': [100, 25, 14],
'formattedValue': ['100', '25', '14'],
'value': [100, 24, 13],
'formattedValue': ['100', '24', '13'],
'hasData': [True, True, True],
'link': [
'/trends/explore?q=/m/0663v&date=2021-01-01+2021-12-31',
'/trends/explore?q=/m/09cfq&date=2021-01-01+2021-12-31',
'/trends/explore?q=/m/03clwm&date=2021-01-01+2021-12-31',
'/trends/explore?q=/m/03clwm&date=2021-01-01+2021-12-31'
],
'topic_mid': ['/m/0663v', '/m/09cfq', '/m/03clwm'],
'topic_title': ['Pizza', 'Pizza Hut', "Domino's Pizza"],
'topic_type': ['Dish', 'Restaurant company', 'Restaurant company']
'topic_type': ['Dish', 'Restaurant company', 'Restaurant company'],
}),
df_tail=pd.DataFrame({
'value': [0, 0, 0],
Expand All @@ -350,17 +350,17 @@ def test_related_topics_result_rising():
pytrend.build_payload(kw_list=['pizza'], timeframe='2021-01-01 2021-12-31')
df_result = pytrend.related_topics()['pizza']['rising']
df_expected = pd.DataFrame({
'value': [11800, 170, 90, 80],
'formattedValue': ['Breakout', '+170%', '+90%', '+80%'],
'value': [12100, 160, 80, 80],
'formattedValue': ['Breakout', '+160%', '+80%', '+80%'],
'link': [
'/trends/explore?q=/m/09nghg&date=2021-01-01+2021-12-31',
'/trends/explore?q=/m/0gwh_4&date=2021-01-01+2021-12-31',
'/trends/explore?q=/g/11g6qhxwmd&date=2021-01-01+2021-12-31',
'/trends/explore?q=/m/02hvyj&date=2021-01-01+2021-12-31',
'/trends/explore?q=/g/11g6qhxwmd&date=2021-01-01+2021-12-31'
],
'topic_mid': ['/m/09nghg', '/m/0gwh_4', '/g/11g6qhxwmd', '/m/02hvyj'],
'topic_title': ['Sam Goody', 'Detroit-style pizza', 'Ooni', 'Mystic Pizza'],
'topic_type': ['Retail company', 'Food', 'Topic', '1988 film']
'topic_mid': ['/m/09nghg', '/m/0gwh_4', '/m/02hvyj', '/g/11g6qhxwmd'],
'topic_title': ['Sam Goody', 'Detroit-style pizza', 'Mystic Pizza', 'Ooni'],
'topic_type': ['Retail company', 'Food', '1988 film', 'Topic'],
})
assert_frame_equal(df_result, df_expected)

Expand All @@ -387,11 +387,11 @@ def test_related_queries_result_top():
length=25,
df_head=pd.DataFrame({
'query': ['pizza hut', 'pizza near me', 'pizza pizza near me'],
'value': [100, 64, 64]
'value': [100, 67, 65],
}),
df_tail=pd.DataFrame({
'query': ['cheese pizza', 'little caesars', 'pizza little caesars'],
'value': [5, 5, 5]
'query': ['pizza papa johns', 'little caesars', 'boston pizza'],
'value': [5, 5, 5],
}, index=pd.Index([22, 23, 24]))
)
expected_pizza.assert_equals(df_result['pizza']['top'])
Expand All @@ -400,11 +400,11 @@ def test_related_queries_result_top():
length=25,
df_head=pd.DataFrame({
'query': ['the bagel', 'bagel me', 'bagel near me'],
'value': [100, 99, 93]
'value': [100, 92, 85],
}),
df_tail=pd.DataFrame({
'query': ['coffee meets bagel', 'bagel bread', 'what a bagel'],
'value': [23, 22, 21]
'query': ['manhattan bagel', 'bagel sandwich', 'what a bagel'],
'value': [21, 21, 20],
}, index=pd.Index([22, 23, 24]))
)
expected_bagel.assert_equals(df_result['bagel']['top'])
Expand All @@ -417,27 +417,27 @@ def test_related_queries_result_rising():
df_result = pytrend.related_queries()

expected_pizza = ExpectedResult(
length=11,
length=13,
df_head=pd.DataFrame({
'query': ['licorice pizza', 'history of pizza', 'stoned pizza'],
'value': [8850, 400, 300]
'value': [9100, 400, 300],
}),
df_tail=pd.DataFrame({
'query': ['pizza cosy', 'incredible pizza', 'andys pizza'],
'value': [50, 50, 50]
}, index=pd.Index([8, 9, 10]))
'query': ['mountain mike pizza', 'pizza raul', 'pizza cosy'],
'value': [50, 50, 50],
}, index=pd.Index([10, 11, 12]))
)
expected_pizza.assert_equals(df_result['pizza']['rising'])

expected_bagel = ExpectedResult(
length=19,
df_head=pd.DataFrame({
'query': ['rover bagel', 'kettlemans bagel', 'bagel karen'],
'value': [400, 250, 170]
'value': [450, 250, 190],
}),
df_tail=pd.DataFrame({
'query': ['brugger bagel', 'the bagel nook', 'best bagel near me'],
'value': [50, 40, 40]
'query': ['bagel street deli', 'best bagel near me', 'bloomington bagel company'],
'value': [40, 40, 40],
}, index=pd.Index([16, 17, 18]))
)
expected_bagel.assert_equals(df_result['bagel']['rising'])
Expand All @@ -452,9 +452,9 @@ def test_trending_searches_ok():
# They're time-dependent.
expected_result = ExpectedResult(
length=20,
df_head=pd.DataFrame({0: ['Michigan football', 'Seoul', 'Penn State football']}),
df_head=pd.DataFrame({0: ['Kevin Conroy', 'Gallagher', 'Student loan forgiveness']}),
df_tail=pd.DataFrame(
{0: ['Myositis', 'Dogecoin', 'Deion Sanders']},
{0: ['Nick Cannon', 'CPI', 'Daytona Beach']},
index=pd.Index([17, 18, 19])
)
)
Expand All @@ -473,45 +473,42 @@ def test_realtime_trending_searches_ok():
# Rebuilding a full 3-head-tail result from scratch is a chore, with a single record for head
# and tail is more than enough.
expected_result = ExpectedResult(
length=131,
length=122,
head_tail_length=1,
df_head=pd.DataFrame({
'title': [
('Michigan Wolverines football, '
'Michigan State Spartans football, '
'American football, '
'Big Ten Conference'),
("Gonzaga Bulldogs men's basketball, "
"Michigan State Spartans men's basketball, "
'College basketball, '
'Armed Forces Classic, '
'Michigan State Spartans football')
],
'entityNames': [
[
'Michigan Wolverines football',
"Gonzaga Bulldogs men's basketball",
"Michigan State Spartans men's basketball",
'College basketball',
'Armed Forces Classic',
'Michigan State Spartans football',
'American football',
'Big Ten Conference'
],
]
}),
df_tail=pd.DataFrame({
'title': [
('Florida Gulf Coast University, '
'ASUN Conference, '
'Kennesaw State University, '
'Cross country running, '
'Volleyball, '
"Florida Gulf Coast Eagles men's basketball, "
'NCAA Division I')
], 'entityNames': [
('Wake Forest University, '
'Georgia Bulldogs football, '
'Atlantic Coast Conference, '
'College basketball')
],
'entityNames': [
[
'Florida Gulf Coast University',
'ASUN Conference',
'Kennesaw State University',
'Cross country running',
'Volleyball',
"Florida Gulf Coast Eagles men's basketball",
'NCAA Division I'
]
'Wake Forest University',
'Georgia Bulldogs football',
'Atlantic Coast Conference',
'College basketball'
],
]
}, index=pd.Index([130]))
}, index=pd.Index([121]))
)
expected_result.assert_equals(df_result)

Expand Down Expand Up @@ -566,12 +563,12 @@ def test_interest_over_time_partial():

def test_request_args_passing(mocked_responses):
mocked_responses.add(
url='https://trends.google.com/?geo=US',
url=f'{BASE_TRENDS_URL}/?geo=US',
method='GET',
match=[responses.matchers.header_matcher({'User-Agent': 'pytrends'})]
)
mocked_responses.add(
url='https://trends.google.com/trends/hottrends/visualize/internal/data',
url=TrendReq.TRENDING_SEARCHES_URL,
method='GET',
match=[responses.matchers.header_matcher({'User-Agent': 'pytrends'})],
json={
Expand Down

0 comments on commit 0d6113a

Please sign in to comment.