Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TF-1627 Update same_query_across_sites example #35

Merged
merged 7 commits into from
Aug 13, 2024
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions examples/compare_product_prices/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# Example script: comparing product price across websites with AgentQL

This example demonstrates how to compare product prices across websites with query_data() method.

## Run the script

* [Install AgentQL SDK](https://docs.agentql.com/docs/installation/sdk-installation)
* Save this python file locally as **compare_product_prices.py**
* Run the following command from the project's folder:
```bash
python3 compare_product_prices.py
```

## Play with it
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This heading can be confusing. First heading is "Run the script", second "Play with it" reads like "Play with the script". What about "Play with the query"?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is a great suggestion!


Install the [AgentQL Chrome DevTools extension](https://docs.agentql.com/docs/installation/chrome-extension-installation/) to play with the AgentQL query. [Learn more about the AgentQL query language](https://docs.agentql.com/docs/agentql-query/query-intro)
67 changes: 67 additions & 0 deletions examples/compare_product_prices/compare_product_prices.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
"""This example demonstrates how to compare product prices across websites with query_data() method."""

from agentql.ext.playwright.sync_api import Page
from playwright.sync_api import sync_playwright

# Set the URL to the desired website
BESTBUY_URL = "https://www.bestbuy.com/site/nintendo-switch-oled-model-w-joy-con-white/6470923.p?skuId=6470923"
TARGET_URL = "https://www.target.com/p/nintendo-switch-oled-model-with-white-joy-con/-/A-83887639#lnk=sametab"
NINETENDO_URL = "https://www.nintendo.com/us/store/products/nintendo-switch-oled-model-white-set/"

# Define the queries to get the product price
PRODUCT_INFO_QUERY = """
{
nintendo_switch
{
price
}
}
"""


def print_header():
"""Prints the header for the data table"""
print(f"{'Website':<25} | {'Product ':<20} | {'Price ':<20} ")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's use https://pypi.org/project/prettytable/ to not reinvent the wheel

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm a little hesitant to use prettytable library here because it's not included in Python standard library and requires pip install prettytable. I guess it depends on what kind of customer journey we want to provide to users. If we expect users to find this example through link on our documentation website and then copy / paste the code into their project. Then any extra setup requirement would create an issue.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's a matter of providing clear instructions. In reality people would not use our code to print tables, they probably won't print tables to console at all, tbh. You can rewrite this code in a shape of preparing the data first (which everyone can copy-paste, and then outputting them second (which can be ignored).

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Understood! You're absolutely right that people would not print tables. In this case, I will probably remove the outputting table part entirely. Because I feel like even with clear instructions, there will be a fairly large amount of users who will just copy/paste the code, run it, find out the code does not work, and then try to figure out what's going on. And the purpose of these examples is just to demonstrate the core functionality of AgentQL.

print("-" * 75)


def print_row(website, product, price):
"""Prints the data row"""
print(f"{website:<25} | {product:<20} | {price:<20} ")


def main():
print_header()

with sync_playwright() as playwright:
browser = playwright.chromium.launch(headless=False)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

not specific to this example, but what do you think about moving browser creation into with block as well, to automanage it as a resource?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that's a good idea and will save users the pain of both creating browser and stopping browser.

But to do this, we probably need to create our own context manager API that wraps around the launch() method to make it work in both sync and async environment.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It works out of the box


# Create a new AgentQL page instance in the browser for web interactions
page: Page = browser.new_page() # type: ignore

page.goto(BESTBUY_URL)

# Use query_data() method to fetch the price from the BestBuy page
response = page.query_data(PRODUCT_INFO_QUERY)

print_row("BestBuy", "Nintendo Switch", response["nintendo_switch"]["price"])

Check failure on line 47 in examples/compare_product_prices/compare_product_prices.py

View workflow job for this annotation

GitHub Actions / Pre-commit checks

Argument of type "Literal['price']" cannot be assigned to parameter "key" of type "SupportsIndex | slice" in function "__getitem__"   Type "Literal['price']" is incompatible with type "SupportsIndex | slice"     "Literal['price']" is incompatible with protocol "SupportsIndex"       "__index__" is not present     "Literal['price']" is incompatible with "slice" (reportArgumentType)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should fix the source of these check failures


page.goto(NINETENDO_URL)

# Use query_data() method to fetch the price from the Nintendo page
response = page.query_data(PRODUCT_INFO_QUERY)

print_row("Nintendo site", "Nintendo Switch", response["nintendo_switch"]["price"])

Check failure on line 54 in examples/compare_product_prices/compare_product_prices.py

View workflow job for this annotation

GitHub Actions / Pre-commit checks

Argument of type "Literal['price']" cannot be assigned to parameter "key" of type "SupportsIndex | slice" in function "__getitem__"   Type "Literal['price']" is incompatible with type "SupportsIndex | slice"     "Literal['price']" is incompatible with protocol "SupportsIndex"       "__index__" is not present     "Literal['price']" is incompatible with "slice" (reportArgumentType)

page.goto(TARGET_URL)

# Use query_data() method to fetch the price from the Target page
response = page.query_data(PRODUCT_INFO_QUERY)

print_row("Target", "Nintendo Switch", response["nintendo_switch"]["price"])

Check failure on line 61 in examples/compare_product_prices/compare_product_prices.py

View workflow job for this annotation

GitHub Actions / Pre-commit checks

Argument of type "Literal['price']" cannot be assigned to parameter "key" of type "SupportsIndex | slice" in function "__getitem__"   Type "Literal['price']" is incompatible with type "SupportsIndex | slice"     "Literal['price']" is incompatible with protocol "SupportsIndex"       "__index__" is not present     "Literal['price']" is incompatible with "slice" (reportArgumentType)

browser.close()


if __name__ == "__main__":
main()
73 changes: 0 additions & 73 deletions examples/same_query_across_sites/same_query_across_sites.py

This file was deleted.

Loading