Repository: openstates/openstates-scrapers

Issue:
MD failing since at least 2018-03-21
MD has been failing since 2018-03-21

Based on automated runs it appears that MD has not run successfully in 2 days (2018-03-21).


```
  00:11:44 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1264&stab=01&pid=billpage&tab=subject3&ys=2018rs
00:11:45 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1264&stab=02&pid=billpage&tab=subject3&ys=2018rs
00:11:46 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1264&stab=03&pid=billpage&tab=subject3&ys=2018rs
00:11:47 INFO pupa: save bill SB1264 in 2018 as bill_83ec5610-2d8f-11e8-aee5-0a58a9feac2a.json
00:11:47 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1265&stab=01&pid=billpage&tab=subject3&ys=2018rs
00:11:48 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1265&stab=02&pid=billpage&tab=subject3&ys=2018rs
00:11:49 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1265&stab=03&pid=billpage&tab=subject3&ys=2018rs
00:11:50 INFO pupa: save bill SB1265 in 2018 as bill_85b76b24-2d8f-11e8-aee5-0a58a9feac2a.json
00:11:50 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1266&stab=01&pid=billpage&tab=subject3&ys=2018rs
00:11:51 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1266&stab=02&pid=billpage&tab=subject3&ys=2018rs
00:11:52 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1266&stab=03&pid=billpage&tab=subject3&ys=2018rs
00:11:53 INFO pupa: save bill SB1266 in 2018 as bill_87b2c0e0-2d8f-11e8-aee5-0a58a9feac2a.json
00:11:53 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1267&stab=01&pid=billpage&tab=subject3&ys=2018rs
00:11:54 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1267&stab=02&pid=billpage&tab=subject3&ys=2018rs
00:11:55 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1267&stab=03&pid=billpage&tab=subject3&ys=2018rs
00:11:56 INFO pupa: save bill SB1267 in 2018 as bill_894abcdc-2d8f-11e8-aee5-0a58a9feac2a.json
00:11:56 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1268&stab=01&pid=billpage&tab=subject3&ys=2018rs
00:11:57 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1268&stab=02&pid=billpage&tab=subject3&ys=2018rs
00:11:58 INFO scrapelib: GET - http://mgaleg.maryland.gov/webmga/frmMain.aspx?id=SB1268&stab=03&pid=billpage&tab=subject3&ys=2018rs
00:11:59 INFO scrapelib: GET - http://mgaleg.maryland.gov/2018RS/votes/Senate/0569.pdf
00:12:00 ERROR pupa: Motion Extracted: 
loaded Open States pupa settings...
md (scrape, import)
  bills: {}
  people: {}
  committees: {}
Traceback (most recent call last):
  File "/opt/openstates/venv-pupa//bin/pupa", line 11, in <module>
    load_entry_point('pupa', 'console_scripts', 'pupa')()
  File "/opt/openstates/venv-pupa/src/pupa/pupa/cli/__main__.py", line 68, in main
    subcommands[args.subcommand].handle(args, other)
  File "/opt/openstates/venv-pupa/src/pupa/pupa/cli/commands/update.py", line 260, in handle
    return self.do_handle(args, other, juris)
  File "/opt/openstates/venv-pupa/src/pupa/pupa/cli/commands/update.py", line 305, in do_handle
    report['scrape'] = self.do_scrape(juris, args, scrapers)
  File "/opt/openstates/venv-pupa/src/pupa/pupa/cli/commands/update.py", line 173, in do_scrape
    report[scraper_name] = scraper.do_scrape(**scrape_args)
  File "/opt/openstates/venv-pupa/src/pupa/pupa/scrape/base.py", line 111, in do_scrape
    for obj in self.scrape(**kwargs) or []:
  File "/opt/openstates/openstates/openstates/md/bills.py", line 544, in scrape
    yield from self.scrape_chamber(chamber, session)
  File "/opt/openstates/openstates/openstates/md/bills.py", line 573, in scrape_chamber
    yield from self.scrape_bill(chamber, session, bill_id, url)
  File "/opt/openstates/openstates/openstates/md/bills.py", line 451, in scrape_bill
    yield from self.parse_bill_votes_new(doc, bill)
  File "/opt/openstates/openstates/openstates/md/bills.py", line 180, in parse_bill_votes_new
    vote = self.parse_vote_pdf(href, bill)
  File "/opt/openstates/openstates/openstates/md/bills.py", line 238, in parse_vote_pdf
    raise ValueError("No Motion or faulty Motion scraped.")
ValueError: No Motion or faulty Motion scraped.
```

Visit http://bobsled.openstates.org for more info.



Discussion:
Looking into it.

Resolving patch:
diff --git a/openstates/md/bills.py b/openstates/md/bills.py
--- a/openstates/md/bills.py
+++ b/openstates/md/bills.py
@@ -222,20 +222,23 @@ def parse_vote_pdf(self, vote_url, bill):
         # eg, http://mgaleg.maryland.gov/2018RS/votes/Senate/0478.pdf
         is_consent_calendar = any(['Consent Calendar' in line for line in lines[:page_index]])
         consent_calendar_bills = None
+        motion = ""
         if is_consent_calendar:
             motion = re.split(r'\s{2,}', lines[page_index - 4].strip())[0]
             consent_calendar_bills = re.split(r'\s{2,}', lines[page_index-1].strip())
             assert consent_calendar_bills, "Could not find bills for consent calendar vote"
-        else:
-            motion = re.split(r'\s{2,}', lines[page_index-3].strip())[0]
 
         motion_keywords = ['favorable', 'reading', 'amendment', 'motion', 'introduced']
+        motion_lines = [3, 2, 4, 5]  # Relative LineNumbers to be checked for existence of motion
 
-        if not any(motion_keyword in motion.lower() for motion_keyword in motion_keywords):
-            motion = re.split(r'\s{2,}', lines[page_index-2].strip())[0]
-        if not any(motion_keyword in motion.lower() for motion_keyword in motion_keywords):
-            self.error("Motion Extracted: %s" % motion)
-            raise ValueError("No Motion or faulty Motion scraped.")
+        for i in motion_lines:
+            if any(motion_keyword in motion.lower() for motion_keyword in motion_keywords):
+                break
+            motion = re.split(r'\s{2,}', lines[page_index-i].strip())[0]
+        else:
+            if not any(motion_keyword in motion.lower() for motion_keyword in motion_keywords):
+                self.error("Motion Extracted: %s" % motion)
+                raise ValueError("No Motion or faulty Motion scraped.")
 
         vote = VoteEvent(
             bill=bill,


Test patch: