coddingtonbear / python-myfitnesspal

Access your meal tracking data stored in MyFitnessPal programatically
MIT License
794 stars 136 forks source link

Some search results break the search function #105

Closed thebutthutt closed 2 years ago

thebutthutt commented 4 years ago

Found searching for "peanut butter" gave me the error

Traceback (most recent call last):
  File "c:/Users/panca/Projects/MFPAPI/ouch.py", line 3, in <module>
    print(client.get_food_search_results("peanut butter"))
  File "C:\Python38\lib\site-packages\myfitnesspal\client.py", line 681, in get_food_search_results
    return self._get_food_search_results(document)
  File "C:\Python38\lib\site-packages\myfitnesspal\client.py", line 699, in _get_food_search_results
    item_div.xpath(".//p[@class='search-nutritional-info']")[0]
IndexError: list index out of range

Even though that paragraph does actually seem to exist, it died. I fixed it below! file client.py

def _get_food_search_results(self, document) -> List[FoodItem]:
        item_divs = document.xpath("//li[@class='matched-food']")

        items = []
        for item_div in item_divs:
            if (len(item_div.xpath(".//p[@class='search-nutritional-info']"))):          <------------------ If the paragraph exists, add it
                # get mfp info from search results
                a = item_div.xpath(
                    ".//div[@class='search-title-container']/a")[0]
                mfp_id = int(a.get("data-external-id"))
                mfp_name = a.text
                verif = (
                    True
                    if item_div.xpath(".//div[@class='verified verified-list-icon']")
                    else False
                )
                nutr_info = (
                    item_div.xpath(".//p[@class='search-nutritional-info']")[0]
                    .text.strip()
                    .split(",")
                )
                brand = ""
                if len(nutr_info) >= 3:
                    brand = " ".join(nutr_info[0:-2]).strip()
                calories = float(nutr_info[-1].replace("calories", "").strip())
                items.append(
                    FoodItem(mfp_id, mfp_name, brand,
                             verif, calories, client=self)
                )
            else:                                                                       <----------------- otherwise go to the next item
                continue

        return items
coddingtonbear commented 4 years ago

Looking at the fix you've proposed, it looks like you'll just skip rows that are missing that class; is that actually the right approach?

thebutthutt commented 3 years ago

I wondered about that too, but weirdly, the lines with issues contained parentheses, but when I checked the output, those lines were still there. I still counted 100 entries displayed too, so I didn't seem to be losing any data

coddingtonbear commented 2 years ago

Forgive me, for the moment I'm going to close this; if you did want to put together a PR, definitely feel free to post one. If you do post a PR, I wonder if I could convince you into including an example page that exhibits this problem -- I don't think I've seen it myself, but that doesn't at all mean it's not happening!

Cheers and thanks for the bug report!