prompt: We are currently solving the following issue within our repository. Here is the issue text:
  --- BEGIN ISSUE ---
  MI scraper failing since at least 2017-04-01
  MI has been failing since 2017-04-01
  
  Based on automated runs it appears that MI has not run successfully in 5 days (2017-04-01).
  
  
  ```
    06:00:31 INFO billy: billy-update abbr=mi
      actions=scrape,import,report
      types=bills,legislators,votes,committees,alldata,events
      sessions=2017-2018
      terms=2017-2018
  06:00:31 INFO scrapelib: GET - http://www.senate.michigan.gov/senatorinfo.html
    File "/usr/local/bin/billy-update", line 9, in <module>
      load_entry_point('billy==1.9.0', 'console_scripts', 'billy-update')()
    File "/opt/openstates/billy/billy/bin/update.py", line 368, in main
  Traceback (most recent call last):
      run_record += _run_scraper(stype, args, metadata)
    File "/opt/openstates/billy/billy/bin/update.py", line 102, in _run_scraper
      response = self.get(url)
    File "/usr/local/lib/python2.7/dist-packages/requests/sessions.py", line 501, in get
      return self.request('GET', url, **kwargs)
    File "/usr/local/lib/python2.7/dist-packages/scrapelib/__init__.py", line 272, in request
      raise HTTPError(resp)
  scrapelib.HTTPError: 500 while retrieving http://www.senate.michigan.gov/senatorinfo.html
    File "/srv/openstates-web/openstates/mi/legislators.py", line 77, in scrape_upper
      scraper.scrape(chamber, time)
    File "/srv/openstates-web/openstates/mi/legislators.py", line 16, in scrape
      return self.scrape_upper(chamber, term)
      doc = self.lxmlize(url)
    File "/srv/openstates-web/openstates/utils/lxmlize.py", line 19, in lxmlize
  ```
  
  Visit http://bobsled.openstates.org/ for more info.
  
  
  --- END ISSUE ---
  
  Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
  --- BEGIN FILES ---
  Path: `openstates/mi/legislators.py`
  Content:
  ```
  1 import re
  2 
  3 from billy.scrape.legislators import LegislatorScraper, Legislator
  4 from openstates.utils import LXMLMixin
  5 
  6 abbr = {'D': 'Democratic', 'R': 'Republican'}
  7 
  8 
  9 class MILegislatorScraper(LegislatorScraper, LXMLMixin):
  10     jurisdiction = 'mi'
  11 
  12     def scrape(self, chamber, term):
  13         self.validate_term(term, latest_only=True)
  14         if chamber == 'lower':
  15             return self.scrape_lower(chamber, term)
  16         return self.scrape_upper(chamber, term)
  17 
  18     def scrape_lower(self, chamber, term):
  19         url = 'http://www.house.mi.gov/mhrpublic/frmRepList.aspx'
  20         table = [
  21             "website",
  22             "district",
  23             "name",
  24             "party",
  25             "location",
  26             "phone",
  27             "email"
  28         ]
  29         doc = self.lxmlize(url)
  30         # skip two rows at top
  31         for row in doc.xpath('//table[@id="grvRepInfo"]/*'):
  32             tds = row.xpath('.//td')
  33             if len(tds) == 0:
  34                 continue
  35             metainf = {}
  36             for i in range(0, len(table)):
  37                 metainf[table[i]] = tds[i]
  38             district = str(int(metainf['district'].text_content().strip()))
  39             party = metainf['party'].text_content().strip()
  40             phone = metainf['phone'].text_content().strip()
  41             email = metainf['email'].text_content().strip()
  42             leg_url = metainf['website'].xpath("./a")[0].attrib['href']
  43             name = metainf['name'].text_content().strip()
  44             if name == 'Vacant' or re.match(r'^District \d{1,3}$', name):
  45                 self.warning('District {} appears vacant, and will be skipped'.format(district))
  46                 continue
  47 
  48             office = metainf['location'].text_content().strip()
  49             office = re.sub(
  50                     ' HOB',
  51                     ' Anderson House Office Building\n124 North Capitol Avenue\nLansing, MI 48933',
  52                     office
  53                     )
  54             office = re.sub(
  55                     ' CB',
  56                     ' State Capitol Building\nLansing, MI 48909',
  57                     office
  58                     )
  59 
  60             leg = Legislator(term=term,
  61                              chamber=chamber,
  62                              full_name=name,
  63                              district=district,
  64                              party=abbr[party],
  65                              url=leg_url)
  66 
  67             leg.add_office('capitol', 'Capitol Office',
  68                            address=office,
  69                            phone=phone,
  70                            email=email)
  71 
  72             leg.add_source(url)
  73             self.save_legislator(leg)
  74 
  75     def scrape_upper(self, chamber, term):
  76         url = 'http://www.senate.michigan.gov/senatorinfo.html'
  77         doc = self.lxmlize(url)
  78         for row in doc.xpath('//table[not(@class="calendar")]//tr')[3:]:
  79             if len(row) != 7:
  80                 continue
  81 
  82             # party, dist, member, office_phone, office_fax, office_loc
  83             party, dist, member, contact, phone, fax, loc = row.getchildren()
  84             if (party.text_content().strip() == "" or
  85                     'Lieutenant Governor' in member.text_content()):
  86                 continue
  87 
  88             party = abbr[party.text]
  89             district = dist.text_content().strip()
  90             name = member.text_content().strip()
  91             name = re.sub(r'\s+', " ", name)
  92 
  93             if name == 'Vacant':
  94                 self.info('district %s is vacant', district)
  95                 continue
  96 
  97             leg_url = member.xpath('a/@href')[0]
  98             office_phone = phone.text
  99             office_fax = fax.text
  100 
  101             office_loc = loc.text
  102             office_loc = re.sub(
  103                     ' Farnum Bldg',
  104                     ' Farnum Office Building\n125 West Allegan Street\nLansing, MI 48933',
  105                     office_loc
  106                     )
  107             office_loc = re.sub(
  108                     ' Capitol Bldg',
  109                     ' State Capitol Building\nLansing, MI 48909',
  110                     office_loc
  111                     )
  112 
  113             leg = Legislator(term=term, chamber=chamber,
  114                              district=district,
  115                              full_name=name,
  116                              party=party,
  117                              url=leg_url)
  118 
  119             leg.add_office('capitol', 'Capitol Office',
  120                            address=office_loc,
  121                            fax=office_fax,
  122                            phone=office_phone)
  123 
  124             leg.add_source(url)
  125             self.save_legislator(leg)
  126
  ```
  --- END FILES ---
  
  Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.
  
  Here is an example:
  
  ```diff
  diff --git a/examples/server_async.py b/examples/server_async.py
  --- a/examples/server_async.py
  +++ b/examples/server_async.py
  @@ -313,4 +313,4 @@
   
   
   if __name__ == "__main__":
  -    asyncio.run(run_async_server("."), debug=True)
  +    asyncio.run(run_async_server(), debug=True)
  diff --git a/examples/server_sync.py b/examples/server_sync.py
  --- a/examples/server_sync.py
  +++ b/examples/server_sync.py
  @@ -313,5 +313,5 @@
   
   
   if __name__ == "__main__":
  -    server = run_sync_server(".")
  +    server = run_sync_server()
       server.shutdown()
  
  ```
  
golden_diff: diff --git a/openstates/mi/legislators.py b/openstates/mi/legislators.py
  --- a/openstates/mi/legislators.py
  +++ b/openstates/mi/legislators.py
  @@ -73,7 +73,7 @@
               self.save_legislator(leg)
   
       def scrape_upper(self, chamber, term):
  -        url = 'http://www.senate.michigan.gov/senatorinfo.html'
  +        url = 'http://www.senate.michigan.gov/senatorinfo_list.html'
           doc = self.lxmlize(url)
           for row in doc.xpath('//table[not(@class="calendar")]//tr')[3:]:
               if len(row) != 7:
  
verification_info: {"golden_diff": "diff --git a/openstates/mi/legislators.py b/openstates/mi/legislators.py\n--- a/openstates/mi/legislators.py\n+++ b/openstates/mi/legislators.py\n@@ -73,7 +73,7 @@\n             self.save_legislator(leg)\n \n     def scrape_upper(self, chamber, term):\n-        url = 'http://www.senate.michigan.gov/senatorinfo.html'\n+        url = 'http://www.senate.michigan.gov/senatorinfo_list.html'\n         doc = self.lxmlize(url)\n         for row in doc.xpath('//table[not(@class=\"calendar\")]//tr')[3:]:\n             if len(row) != 7:\n", "issue": "MI scraper failing since at least 2017-04-01\nMI has been failing since 2017-04-01\n\nBased on automated runs it appears that MI has not run successfully in 5 days (2017-04-01).\n\n\n```\n  06:00:31 INFO billy: billy-update abbr=mi\n    actions=scrape,import,report\n    types=bills,legislators,votes,committees,alldata,events\n    sessions=2017-2018\n    terms=2017-2018\n06:00:31 INFO scrapelib: GET - http://www.senate.michigan.gov/senatorinfo.html\n  File \"/usr/local/bin/billy-update\", line 9, in <module>\n    load_entry_point('billy==1.9.0', 'console_scripts', 'billy-update')()\n  File \"/opt/openstates/billy/billy/bin/update.py\", line 368, in main\nTraceback (most recent call last):\n    run_record += _run_scraper(stype, args, metadata)\n  File \"/opt/openstates/billy/billy/bin/update.py\", line 102, in _run_scraper\n    response = self.get(url)\n  File \"/usr/local/lib/python2.7/dist-packages/requests/sessions.py\", line 501, in get\n    return self.request('GET', url, **kwargs)\n  File \"/usr/local/lib/python2.7/dist-packages/scrapelib/__init__.py\", line 272, in request\n    raise HTTPError(resp)\nscrapelib.HTTPError: 500 while retrieving http://www.senate.michigan.gov/senatorinfo.html\n  File \"/srv/openstates-web/openstates/mi/legislators.py\", line 77, in scrape_upper\n    scraper.scrape(chamber, time)\n  File \"/srv/openstates-web/openstates/mi/legislators.py\", line 16, in scrape\n    return self.scrape_upper(chamber, term)\n    doc = self.lxmlize(url)\n  File \"/srv/openstates-web/openstates/utils/lxmlize.py\", line 19, in lxmlize\n```\n\nVisit http://bobsled.openstates.org/ for more info.\n\n", "before_files": [{"content": "import re\n\nfrom billy.scrape.legislators import LegislatorScraper, Legislator\nfrom openstates.utils import LXMLMixin\n\nabbr = {'D': 'Democratic', 'R': 'Republican'}\n\n\nclass MILegislatorScraper(LegislatorScraper, LXMLMixin):\n    jurisdiction = 'mi'\n\n    def scrape(self, chamber, term):\n        self.validate_term(term, latest_only=True)\n        if chamber == 'lower':\n            return self.scrape_lower(chamber, term)\n        return self.scrape_upper(chamber, term)\n\n    def scrape_lower(self, chamber, term):\n        url = 'http://www.house.mi.gov/mhrpublic/frmRepList.aspx'\n        table = [\n            \"website\",\n            \"district\",\n            \"name\",\n            \"party\",\n            \"location\",\n            \"phone\",\n            \"email\"\n        ]\n        doc = self.lxmlize(url)\n        # skip two rows at top\n        for row in doc.xpath('//table[@id=\"grvRepInfo\"]/*'):\n            tds = row.xpath('.//td')\n            if len(tds) == 0:\n                continue\n            metainf = {}\n            for i in range(0, len(table)):\n                metainf[table[i]] = tds[i]\n            district = str(int(metainf['district'].text_content().strip()))\n            party = metainf['party'].text_content().strip()\n            phone = metainf['phone'].text_content().strip()\n            email = metainf['email'].text_content().strip()\n            leg_url = metainf['website'].xpath(\"./a\")[0].attrib['href']\n            name = metainf['name'].text_content().strip()\n            if name == 'Vacant' or re.match(r'^District \\d{1,3}$', name):\n                self.warning('District {} appears vacant, and will be skipped'.format(district))\n                continue\n\n            office = metainf['location'].text_content().strip()\n            office = re.sub(\n                    ' HOB',\n                    ' Anderson House Office Building\\n124 North Capitol Avenue\\nLansing, MI 48933',\n                    office\n                    )\n            office = re.sub(\n                    ' CB',\n                    ' State Capitol Building\\nLansing, MI 48909',\n                    office\n                    )\n\n            leg = Legislator(term=term,\n                             chamber=chamber,\n                             full_name=name,\n                             district=district,\n                             party=abbr[party],\n                             url=leg_url)\n\n            leg.add_office('capitol', 'Capitol Office',\n                           address=office,\n                           phone=phone,\n                           email=email)\n\n            leg.add_source(url)\n            self.save_legislator(leg)\n\n    def scrape_upper(self, chamber, term):\n        url = 'http://www.senate.michigan.gov/senatorinfo.html'\n        doc = self.lxmlize(url)\n        for row in doc.xpath('//table[not(@class=\"calendar\")]//tr')[3:]:\n            if len(row) != 7:\n                continue\n\n            # party, dist, member, office_phone, office_fax, office_loc\n            party, dist, member, contact, phone, fax, loc = row.getchildren()\n            if (party.text_content().strip() == \"\" or\n                    'Lieutenant Governor' in member.text_content()):\n                continue\n\n            party = abbr[party.text]\n            district = dist.text_content().strip()\n            name = member.text_content().strip()\n            name = re.sub(r'\\s+', \" \", name)\n\n            if name == 'Vacant':\n                self.info('district %s is vacant', district)\n                continue\n\n            leg_url = member.xpath('a/@href')[0]\n            office_phone = phone.text\n            office_fax = fax.text\n\n            office_loc = loc.text\n            office_loc = re.sub(\n                    ' Farnum Bldg',\n                    ' Farnum Office Building\\n125 West Allegan Street\\nLansing, MI 48933',\n                    office_loc\n                    )\n            office_loc = re.sub(\n                    ' Capitol Bldg',\n                    ' State Capitol Building\\nLansing, MI 48909',\n                    office_loc\n                    )\n\n            leg = Legislator(term=term, chamber=chamber,\n                             district=district,\n                             full_name=name,\n                             party=party,\n                             url=leg_url)\n\n            leg.add_office('capitol', 'Capitol Office',\n                           address=office_loc,\n                           fax=office_fax,\n                           phone=office_phone)\n\n            leg.add_source(url)\n            self.save_legislator(leg)\n", "path": "openstates/mi/legislators.py"}], "after_files": [{"content": "import re\n\nfrom billy.scrape.legislators import LegislatorScraper, Legislator\nfrom openstates.utils import LXMLMixin\n\nabbr = {'D': 'Democratic', 'R': 'Republican'}\n\n\nclass MILegislatorScraper(LegislatorScraper, LXMLMixin):\n    jurisdiction = 'mi'\n\n    def scrape(self, chamber, term):\n        self.validate_term(term, latest_only=True)\n        if chamber == 'lower':\n            return self.scrape_lower(chamber, term)\n        return self.scrape_upper(chamber, term)\n\n    def scrape_lower(self, chamber, term):\n        url = 'http://www.house.mi.gov/mhrpublic/frmRepList.aspx'\n        table = [\n            \"website\",\n            \"district\",\n            \"name\",\n            \"party\",\n            \"location\",\n            \"phone\",\n            \"email\"\n        ]\n        doc = self.lxmlize(url)\n        # skip two rows at top\n        for row in doc.xpath('//table[@id=\"grvRepInfo\"]/*'):\n            tds = row.xpath('.//td')\n            if len(tds) == 0:\n                continue\n            metainf = {}\n            for i in range(0, len(table)):\n                metainf[table[i]] = tds[i]\n            district = str(int(metainf['district'].text_content().strip()))\n            party = metainf['party'].text_content().strip()\n            phone = metainf['phone'].text_content().strip()\n            email = metainf['email'].text_content().strip()\n            leg_url = metainf['website'].xpath(\"./a\")[0].attrib['href']\n            name = metainf['name'].text_content().strip()\n            if name == 'Vacant' or re.match(r'^District \\d{1,3}$', name):\n                self.warning('District {} appears vacant, and will be skipped'.format(district))\n                continue\n\n            office = metainf['location'].text_content().strip()\n            office = re.sub(\n                    ' HOB',\n                    ' Anderson House Office Building\\n124 North Capitol Avenue\\nLansing, MI 48933',\n                    office\n                    )\n            office = re.sub(\n                    ' CB',\n                    ' State Capitol Building\\nLansing, MI 48909',\n                    office\n                    )\n\n            leg = Legislator(term=term,\n                             chamber=chamber,\n                             full_name=name,\n                             district=district,\n                             party=abbr[party],\n                             url=leg_url)\n\n            leg.add_office('capitol', 'Capitol Office',\n                           address=office,\n                           phone=phone,\n                           email=email)\n\n            leg.add_source(url)\n            self.save_legislator(leg)\n\n    def scrape_upper(self, chamber, term):\n        url = 'http://www.senate.michigan.gov/senatorinfo_list.html'\n        doc = self.lxmlize(url)\n        for row in doc.xpath('//table[not(@class=\"calendar\")]//tr')[3:]:\n            if len(row) != 7:\n                continue\n\n            # party, dist, member, office_phone, office_fax, office_loc\n            party, dist, member, contact, phone, fax, loc = row.getchildren()\n            if (party.text_content().strip() == \"\" or\n                    'Lieutenant Governor' in member.text_content()):\n                continue\n\n            party = abbr[party.text]\n            district = dist.text_content().strip()\n            name = member.text_content().strip()\n            name = re.sub(r'\\s+', \" \", name)\n\n            if name == 'Vacant':\n                self.info('district %s is vacant', district)\n                continue\n\n            leg_url = member.xpath('a/@href')[0]\n            office_phone = phone.text\n            office_fax = fax.text\n\n            office_loc = loc.text\n            office_loc = re.sub(\n                    ' Farnum Bldg',\n                    ' Farnum Office Building\\n125 West Allegan Street\\nLansing, MI 48933',\n                    office_loc\n                    )\n            office_loc = re.sub(\n                    ' Capitol Bldg',\n                    ' State Capitol Building\\nLansing, MI 48909',\n                    office_loc\n                    )\n\n            leg = Legislator(term=term, chamber=chamber,\n                             district=district,\n                             full_name=name,\n                             party=party,\n                             url=leg_url)\n\n            leg.add_office('capitol', 'Capitol Office',\n                           address=office_loc,\n                           fax=office_fax,\n                           phone=office_phone)\n\n            leg.add_source(url)\n            self.save_legislator(leg)\n", "path": "openstates/mi/legislators.py"}]}